Broadcast an event when sending a mailbox update.

This commit is contained in:
akwizgran
2022-08-03 15:19:42 +01:00
parent 42e2926d61
commit 8657216345
3 changed files with 142 additions and 49 deletions

View File

@@ -0,0 +1,39 @@
package org.briarproject.bramble.api.mailbox.event;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.mailbox.MailboxUpdate;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event that is broadcast when a mailbox update is sent to a contact.
* <p>
* Note that this event is not broadcast when a mailbox is paired or
* unpaired, although updates are sent to all contacts in those situations.
*
* @see MailboxPairedEvent
* @see MailboxUnpairedEvent
*/
@Immutable
@NotNullByDefault
public class MailboxUpdateSentEvent extends Event {
private final ContactId contactId;
private final MailboxUpdate mailboxUpdate;
public MailboxUpdateSentEvent(ContactId contactId,
MailboxUpdate mailboxUpdate) {
this.contactId = contactId;
this.mailboxUpdate = mailboxUpdate;
}
public ContactId getContactId() {
return contactId;
}
public MailboxUpdate getMailboxUpdate() {
return mailboxUpdate;
}
}

View File

@@ -27,6 +27,7 @@ import org.briarproject.bramble.api.mailbox.MailboxUpdateWithMailbox;
import org.briarproject.bramble.api.mailbox.MailboxVersion; import org.briarproject.bramble.api.mailbox.MailboxVersion;
import org.briarproject.bramble.api.mailbox.event.MailboxPairedEvent; import org.briarproject.bramble.api.mailbox.event.MailboxPairedEvent;
import org.briarproject.bramble.api.mailbox.event.MailboxUnpairedEvent; import org.briarproject.bramble.api.mailbox.event.MailboxUnpairedEvent;
import org.briarproject.bramble.api.mailbox.event.MailboxUpdateSentEvent;
import org.briarproject.bramble.api.mailbox.event.RemoteMailboxUpdateEvent; import org.briarproject.bramble.api.mailbox.event.RemoteMailboxUpdateEvent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
@@ -114,6 +115,7 @@ class MailboxUpdateManagerImpl implements MailboxUpdateManager,
} }
Group g = getContactGroup(c); Group g = getContactGroup(c);
storeMessageReplaceLatest(txn, g.getId(), updated); storeMessageReplaceLatest(txn, g.getId(), updated);
txn.attach(new MailboxUpdateSentEvent(c.getId(), updated));
} }
} else { } else {
db.addGroup(txn, localGroup); db.addGroup(txn, localGroup);
@@ -146,14 +148,16 @@ class MailboxUpdateManagerImpl implements MailboxUpdateManager,
clientHelper.setContactId(txn, g.getId(), c.getId()); clientHelper.setContactId(txn, g.getId(), c.getId());
MailboxProperties ownProps = MailboxProperties ownProps =
mailboxSettingsManager.getOwnMailboxProperties(txn); mailboxSettingsManager.getOwnMailboxProperties(txn);
MailboxUpdate u;
if (ownProps != null) { if (ownProps != null) {
// We are paired, create and send props to the newly added contact // We are paired, create and send props to the newly added contact
createAndSendUpdateWithMailbox(txn, c, ownProps.getServerSupports(), u = createAndSendUpdateWithMailbox(txn, c,
ownProps.getOnion()); ownProps.getServerSupports(), ownProps.getOnion());
} else { } else {
// Not paired, but we still want to get our clientSupports sent // Not paired, but we still want to get our clientSupports sent
sendUpdateNoMailbox(txn, c); u = sendUpdateNoMailbox(txn, c);
} }
txn.attach(new MailboxUpdateSentEvent(c.getId(), u));
} }
@Override @Override

View File

@@ -19,6 +19,7 @@ import org.briarproject.bramble.api.mailbox.MailboxUpdateWithMailbox;
import org.briarproject.bramble.api.mailbox.MailboxVersion; import org.briarproject.bramble.api.mailbox.MailboxVersion;
import org.briarproject.bramble.api.mailbox.event.MailboxPairedEvent; import org.briarproject.bramble.api.mailbox.event.MailboxPairedEvent;
import org.briarproject.bramble.api.mailbox.event.MailboxUnpairedEvent; import org.briarproject.bramble.api.mailbox.event.MailboxUnpairedEvent;
import org.briarproject.bramble.api.mailbox.event.MailboxUpdateSentEvent;
import org.briarproject.bramble.api.mailbox.event.RemoteMailboxUpdateEvent; import org.briarproject.bramble.api.mailbox.event.RemoteMailboxUpdateEvent;
import org.briarproject.bramble.api.sync.Group; import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId; import org.briarproject.bramble.api.sync.GroupId;
@@ -185,6 +186,9 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList); MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.onDatabaseOpened(txn); t.onDatabaseOpened(txn);
MailboxUpdateSentEvent e = getEvent(txn, MailboxUpdateSentEvent.class);
assertNoMailboxPropertiesSent(e, someClientSupportsList);
} }
@Test @Test
@@ -238,11 +242,15 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList); MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.onDatabaseOpened(txn); t.onDatabaseOpened(txn);
MailboxUpdateSentEvent e = getEvent(txn, MailboxUpdateSentEvent.class);
assertMailboxPropertiesSent(e, someClientSupportsList);
} }
@Test @Test
public void testUnchangedClientSupportsOnSecondStartup() throws Exception { public void testUnchangedClientSupportsOnSecondStartup() throws Exception {
Transaction txn = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
Transaction txn2 = new Transaction(null, false);
Map<MessageId, BdfDictionary> emptyMessageMetadata = Map<MessageId, BdfDictionary> emptyMessageMetadata =
new LinkedHashMap<>(); new LinkedHashMap<>();
@@ -251,46 +259,49 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
someClientSupports)); someClientSupports));
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).containsGroup(txn, localGroup.getId()); oneOf(db).containsGroup(txn1, localGroup.getId());
will(returnValue(false)); will(returnValue(false));
oneOf(db).addGroup(txn, localGroup); oneOf(db).addGroup(txn1, localGroup);
oneOf(db).getContacts(txn); oneOf(db).getContacts(txn1);
will(returnValue(singletonList(contact))); will(returnValue(singletonList(contact)));
// addingContact() // addingContact()
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact); MAJOR_VERSION, contact);
will(returnValue(contactGroup)); will(returnValue(contactGroup));
oneOf(db).addGroup(txn, contactGroup); oneOf(db).addGroup(txn1, contactGroup);
oneOf(clientVersioningManager).getClientVisibility(txn, oneOf(clientVersioningManager).getClientVisibility(txn1,
contact.getId(), CLIENT_ID, MAJOR_VERSION); contact.getId(), CLIENT_ID, MAJOR_VERSION);
will(returnValue(SHARED)); will(returnValue(SHARED));
oneOf(db).setGroupVisibility(txn, contact.getId(), oneOf(db).setGroupVisibility(txn1, contact.getId(),
contactGroupId, SHARED); contactGroupId, SHARED);
oneOf(clientHelper).setContactId(txn, contactGroupId, oneOf(clientHelper).setContactId(txn1, contactGroupId,
contact.getId()); contact.getId());
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn); oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn1);
will(returnValue(null)); will(returnValue(null));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact); MAJOR_VERSION, contact);
will(returnValue(contactGroup)); will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn, oneOf(clientHelper).getMessageMetadataAsDictionary(txn1,
contactGroupId); contactGroupId);
will(returnValue(emptyMessageMetadata)); will(returnValue(emptyMessageMetadata));
expectStoreMessage(txn, contactGroupId, 1, someClientSupports, expectStoreMessage(txn1, contactGroupId, 1, someClientSupports,
emptyServerSupports, emptyPropsDict); emptyServerSupports, emptyPropsDict);
oneOf(clientHelper).mergeGroupMetadata(txn, localGroup.getId(), oneOf(clientHelper).mergeGroupMetadata(txn1, localGroup.getId(),
sentDict); sentDict);
}}); }});
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList); MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.onDatabaseOpened(txn); t.onDatabaseOpened(txn1);
MailboxUpdateSentEvent e = getEvent(txn1, MailboxUpdateSentEvent.class);
assertNoMailboxPropertiesSent(e, someClientSupportsList);
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).containsGroup(txn, localGroup.getId()); oneOf(db).containsGroup(txn2, localGroup.getId());
will(returnValue(true)); will(returnValue(true));
oneOf(clientHelper).getGroupMetadataAsDictionary(txn, oneOf(clientHelper).getGroupMetadataAsDictionary(txn2,
localGroup.getId()); localGroup.getId());
will(returnValue(sentDict)); will(returnValue(sentDict));
oneOf(clientHelper).parseMailboxVersionList(someClientSupports); oneOf(clientHelper).parseMailboxVersionList(someClientSupports);
@@ -298,13 +309,16 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
}}); }});
t = createInstance(someClientSupportsList); t = createInstance(someClientSupportsList);
t.onDatabaseOpened(txn); t.onDatabaseOpened(txn2);
assertFalse(hasEvent(txn2, MailboxUpdateSentEvent.class));
} }
@Test @Test
public void testSendsUpdateWhenClientSupportsChangedOnSecondStartup() public void testSendsUpdateWhenClientSupportsChangedOnSecondStartup()
throws Exception { throws Exception {
Transaction txn = new Transaction(null, false); Transaction txn1 = new Transaction(null, false);
Transaction txn2 = new Transaction(null, false);
Map<MessageId, BdfDictionary> emptyMessageMetadata = Map<MessageId, BdfDictionary> emptyMessageMetadata =
new LinkedHashMap<>(); new LinkedHashMap<>();
@@ -313,41 +327,45 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
someClientSupports)); someClientSupports));
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).containsGroup(txn, localGroup.getId()); oneOf(db).containsGroup(txn1, localGroup.getId());
will(returnValue(false)); will(returnValue(false));
oneOf(db).addGroup(txn, localGroup); oneOf(db).addGroup(txn1, localGroup);
oneOf(db).getContacts(txn); oneOf(db).getContacts(txn1);
will(returnValue(singletonList(contact))); will(returnValue(singletonList(contact)));
// addingContact() // addingContact()
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact); MAJOR_VERSION, contact);
will(returnValue(contactGroup)); will(returnValue(contactGroup));
oneOf(db).addGroup(txn, contactGroup); oneOf(db).addGroup(txn1, contactGroup);
oneOf(clientVersioningManager).getClientVisibility(txn, oneOf(clientVersioningManager).getClientVisibility(txn1,
contact.getId(), CLIENT_ID, MAJOR_VERSION); contact.getId(), CLIENT_ID, MAJOR_VERSION);
will(returnValue(SHARED)); will(returnValue(SHARED));
oneOf(db).setGroupVisibility(txn, contact.getId(), oneOf(db).setGroupVisibility(txn1, contact.getId(),
contactGroupId, SHARED); contactGroupId, SHARED);
oneOf(clientHelper).setContactId(txn, contactGroupId, oneOf(clientHelper).setContactId(txn1, contactGroupId,
contact.getId()); contact.getId());
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn); oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn1);
will(returnValue(null)); will(returnValue(null));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact); MAJOR_VERSION, contact);
will(returnValue(contactGroup)); will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn, oneOf(clientHelper).getMessageMetadataAsDictionary(txn1,
contactGroupId); contactGroupId);
will(returnValue(emptyMessageMetadata)); will(returnValue(emptyMessageMetadata));
expectStoreMessage(txn, contactGroupId, 1, someClientSupports, expectStoreMessage(txn1, contactGroupId, 1, someClientSupports,
emptyServerSupports, emptyPropsDict); emptyServerSupports, emptyPropsDict);
oneOf(clientHelper).mergeGroupMetadata(txn, localGroup.getId(), oneOf(clientHelper).mergeGroupMetadata(txn1, localGroup.getId(),
sentDict); sentDict);
}}); }});
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList); MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.onDatabaseOpened(txn); t.onDatabaseOpened(txn1);
MailboxUpdateSentEvent e1 =
getEvent(txn1, MailboxUpdateSentEvent.class);
assertNoMailboxPropertiesSent(e1, someClientSupportsList);
BdfDictionary metaDictionary = BdfDictionary.of( BdfDictionary metaDictionary = BdfDictionary.of(
new BdfEntry(MSG_KEY_VERSION, 1), new BdfEntry(MSG_KEY_VERSION, 1),
@@ -356,58 +374,62 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>(); Map<MessageId, BdfDictionary> messageMetadata = new LinkedHashMap<>();
MessageId messageId = new MessageId(getRandomId()); MessageId messageId = new MessageId(getRandomId());
messageMetadata.put(messageId, metaDictionary); messageMetadata.put(messageId, metaDictionary);
BdfList body = BdfList.of(1, someClientSupports, someServerSupports, BdfList oldBody = BdfList.of(1, someClientSupports, emptyServerSupports,
propsDict); emptyPropsDict);
BdfDictionary newerSentDict = BdfDictionary.of(new BdfEntry( BdfDictionary newerSentDict = BdfDictionary.of(new BdfEntry(
GROUP_KEY_SENT_CLIENT_SUPPORTS, GROUP_KEY_SENT_CLIENT_SUPPORTS,
newerClientSupports)); newerClientSupports));
context.checking(new Expectations() {{ context.checking(new Expectations() {{
oneOf(db).containsGroup(txn, localGroup.getId()); oneOf(db).containsGroup(txn2, localGroup.getId());
will(returnValue(true)); will(returnValue(true));
// Find out that we are now on newerClientSupportsList // Find out that we are now on newerClientSupportsList
oneOf(clientHelper).getGroupMetadataAsDictionary(txn, oneOf(clientHelper).getGroupMetadataAsDictionary(txn2,
localGroup.getId()); localGroup.getId());
will(returnValue(sentDict)); will(returnValue(sentDict));
oneOf(clientHelper).parseMailboxVersionList(someClientSupports); oneOf(clientHelper).parseMailboxVersionList(someClientSupports);
will(returnValue(someClientSupportsList)); will(returnValue(someClientSupportsList));
oneOf(db).getContacts(txn); oneOf(db).getContacts(txn2);
will(returnValue(singletonList(contact))); will(returnValue(singletonList(contact)));
oneOf(db).getContact(txn, contact.getId()); oneOf(db).getContact(txn2, contact.getId());
will(returnValue(contact)); will(returnValue(contact));
// getLocalUpdate() // getLocalUpdate()
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact); MAJOR_VERSION, contact);
will(returnValue(contactGroup)); will(returnValue(contactGroup));
oneOf(clientHelper).getMessageMetadataAsDictionary(txn, oneOf(clientHelper).getMessageMetadataAsDictionary(txn2,
contactGroupId); contactGroupId);
will(returnValue(messageMetadata)); will(returnValue(messageMetadata));
oneOf(clientHelper).getMessageAsList(txn, messageId); oneOf(clientHelper).getMessageAsList(txn2, messageId);
will(returnValue(body)); will(returnValue(oldBody));
oneOf(clientHelper).parseAndValidateMailboxUpdate( oneOf(clientHelper).parseAndValidateMailboxUpdate(
someClientSupports, someServerSupports, propsDict); someClientSupports, emptyServerSupports, emptyPropsDict);
will(returnValue(updateWithMailbox)); will(returnValue(updateNoMailbox));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, oneOf(contactGroupFactory).createContactGroup(CLIENT_ID,
MAJOR_VERSION, contact); MAJOR_VERSION, contact);
will(returnValue(contactGroup)); will(returnValue(contactGroup));
// storeMessageReplaceLatest() // storeMessageReplaceLatest()
oneOf(clientHelper).getMessageMetadataAsDictionary(txn, oneOf(clientHelper).getMessageMetadataAsDictionary(txn2,
contactGroupId); contactGroupId);
will(returnValue(messageMetadata)); will(returnValue(messageMetadata));
expectStoreMessage(txn, contactGroupId, 2, expectStoreMessage(txn2, contactGroupId, 2,
newerClientSupports, someServerSupports, propsDict); newerClientSupports, emptyServerSupports, emptyPropsDict);
oneOf(db).removeMessage(txn, messageId); oneOf(db).removeMessage(txn2, messageId);
oneOf(clientHelper).mergeGroupMetadata(txn, localGroup.getId(), oneOf(clientHelper).mergeGroupMetadata(txn2, localGroup.getId(),
newerSentDict); newerSentDict);
}}); }});
t = createInstance(newerClientSupportsList); t = createInstance(newerClientSupportsList);
t.onDatabaseOpened(txn); t.onDatabaseOpened(txn2);
MailboxUpdateSentEvent e2 =
getEvent(txn2, MailboxUpdateSentEvent.class);
assertNoMailboxPropertiesSent(e2, newerClientSupportsList);
} }
@Test @Test
@@ -443,6 +465,9 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList); MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.addingContact(txn, contact); t.addingContact(txn, contact);
MailboxUpdateSentEvent e = getEvent(txn, MailboxUpdateSentEvent.class);
assertNoMailboxPropertiesSent(e, someClientSupportsList);
} }
@Test @Test
@@ -484,6 +509,9 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
MailboxUpdateManagerImpl t = createInstance(someClientSupportsList); MailboxUpdateManagerImpl t = createInstance(someClientSupportsList);
t.addingContact(txn, contact); t.addingContact(txn, contact);
MailboxUpdateSentEvent e = getEvent(txn, MailboxUpdateSentEvent.class);
assertMailboxPropertiesSent(e, someClientSupportsList);
} }
@Test @Test
@@ -693,6 +721,8 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
u.getClientSupports()); u.getClientSupports());
assertEquals(updateWithMailbox.getMailboxProperties(), assertEquals(updateWithMailbox.getMailboxProperties(),
u.getMailboxProperties()); u.getMailboxProperties());
assertFalse(hasEvent(txn, MailboxUpdateSentEvent.class));
} }
@Test @Test
@@ -734,6 +764,8 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
assertEquals(singleton(contact.getId()), localUpdates.keySet()); assertEquals(singleton(contact.getId()), localUpdates.keySet());
MailboxUpdate u = localUpdates.get(contact.getId()); MailboxUpdate u = localUpdates.get(contact.getId());
assertFalse(u.hasMailbox()); assertFalse(u.hasMailbox());
assertFalse(hasEvent(txn, MailboxUpdateSentEvent.class));
} }
@Test @Test
@@ -915,4 +947,22 @@ public class MailboxUpdateManagerImplTest extends BrambleMockTestCase {
false); false);
}}); }});
} }
private void assertNoMailboxPropertiesSent(MailboxUpdateSentEvent e,
List<MailboxVersion> clientSupports) {
assertEquals(contact.getId(), e.getContactId());
MailboxUpdate u = e.getMailboxUpdate();
assertEquals(clientSupports, u.getClientSupports());
assertFalse(u.hasMailbox());
}
private void assertMailboxPropertiesSent(MailboxUpdateSentEvent e,
List<MailboxVersion> clientSupports) {
assertEquals(contact.getId(), e.getContactId());
MailboxUpdate u = e.getMailboxUpdate();
assertEquals(clientSupports, u.getClientSupports());
assertTrue(u.hasMailbox());
MailboxUpdateWithMailbox uMailbox = (MailboxUpdateWithMailbox) u;
assertEquals(updateProps, uMailbox.getMailboxProperties());
}
} }