Merge branch 'blog-sharing-tests' into 'master'

Add unit tests for BlogSharingManager

See merge request !567
This commit is contained in:
akwizgran
2017-07-25 17:40:29 +00:00
2 changed files with 253 additions and 21 deletions

View File

@@ -5,7 +5,6 @@ import net.jodah.concurrentunit.Waiter;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.NoSuchGroupException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@@ -493,26 +492,6 @@ public class BlogSharingIntegrationTest
// 1 can again share blog 1 with 0
assertTrue(
blogSharingManager1.canBeShared(blog1.getId(), contact0From1));
// re-create local state (simulates sign-out and sign-in)
Transaction txn0 = db0.startTransaction(false);
((BlogSharingManagerImpl) blogSharingManager0).createLocalState(txn0);
db0.commitTransaction(txn0);
db0.endTransaction(txn0);
Transaction txn1 = db1.startTransaction(false);
((BlogSharingManagerImpl) blogSharingManager1).createLocalState(txn1);
db1.commitTransaction(txn1);
db1.endTransaction(txn1);
// ensure there's no error with the sessions by checking shareability
assertFalse(
blogSharingManager0.canBeShared(blog1.getId(), contact1From0));
assertTrue(
blogSharingManager1.canBeShared(blog1.getId(), contact0From1));
// contacts should still be able to remove each other without errors
contactManager0.removeContact(contactId1From0);
contactManager1.removeContact(contactId0From1);
}
@Test

View File

@@ -0,0 +1,253 @@
package org.briarproject.briar.sharing;
import org.briarproject.bramble.api.client.ClientHelper;
import org.briarproject.bramble.api.client.ContactGroupFactory;
import org.briarproject.bramble.api.contact.Contact;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.data.BdfDictionary;
import org.briarproject.bramble.api.data.BdfEntry;
import org.briarproject.bramble.api.data.MetadataParser;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Metadata;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.bramble.api.identity.AuthorId;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.sync.Group;
import org.briarproject.bramble.api.sync.GroupId;
import org.briarproject.bramble.api.sync.Message;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.briar.api.blog.Blog;
import org.briarproject.briar.api.blog.BlogInvitationResponse;
import org.briarproject.briar.api.blog.BlogManager;
import org.briarproject.briar.api.client.MessageTracker;
import org.briarproject.briar.api.client.SessionId;
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Test;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.bramble.api.sync.Group.Visibility.SHARED;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getRandomId;
import static org.briarproject.briar.api.blog.BlogSharingManager.CLIENT_ID;
import static org.briarproject.briar.sharing.SharingConstants.GROUP_KEY_CONTACT_ID;
public class BlogSharingManagerImplTest extends BrambleMockTestCase {
private final Mockery context = new Mockery();
private final BlogSharingManagerImpl blogSharingManager;
private final DatabaseComponent db = context.mock(DatabaseComponent.class);
private final IdentityManager identityManager =
context.mock(IdentityManager.class);
private final ClientHelper clientHelper = context.mock(ClientHelper.class);
private final SessionEncoder sessionEncoder =
context.mock(SessionEncoder.class);
private final SessionParser sessionParser =
context.mock(SessionParser.class);
private final ContactGroupFactory contactGroupFactory =
context.mock(ContactGroupFactory.class);
private final BlogManager blogManager = context.mock(BlogManager.class);
private final AuthorId localAuthorId = new AuthorId(getRandomId());
private final ContactId contactId = new ContactId(0);
private final AuthorId authorId = new AuthorId(getRandomId());
private final Author author = new Author(authorId, "Author",
getRandomBytes(MAX_PUBLIC_KEY_LENGTH));
private final Contact contact =
new Contact(contactId, author, localAuthorId, true, true);
private final Collection<Contact> contacts =
Collections.singletonList(contact);
private final Group contactGroup =
new Group(new GroupId(getRandomId()), CLIENT_ID,
getRandomBytes(42));
private final Group blogGroup =
new Group(new GroupId(getRandomId()), BlogManager.CLIENT_ID,
getRandomBytes(42));
private final Blog blog = new Blog(blogGroup, author, false);
@SuppressWarnings("unchecked")
private final ProtocolEngine<Blog> engine =
context.mock(ProtocolEngine.class);
@SuppressWarnings("unchecked")
public BlogSharingManagerImplTest() {
MetadataParser metadataParser = context.mock(MetadataParser.class);
MessageTracker messageTracker = context.mock(MessageTracker.class);
MessageParser<Blog> messageParser = context.mock(MessageParser.class);
InvitationFactory<Blog, BlogInvitationResponse> invitationFactory =
context.mock(InvitationFactory.class);
blogSharingManager =
new BlogSharingManagerImpl(db, clientHelper, metadataParser,
messageParser, sessionEncoder, sessionParser,
messageTracker, contactGroupFactory,
engine, invitationFactory, identityManager,
blogManager);
}
@Test
public void testAddingContactFreshState() throws Exception {
Map<MessageId, BdfDictionary> sessions =
new HashMap<MessageId, BdfDictionary>(0);
testAddingContact(sessions);
}
@Test
public void testAddingContactExistingState() throws Exception {
Map<MessageId, BdfDictionary> sessions =
new HashMap<MessageId, BdfDictionary>(1);
sessions.put(new MessageId(getRandomId()), new BdfDictionary());
testAddingContact(sessions);
}
@Test(expected = DbException.class)
public void testAddingContactMultipleSessions() throws Exception {
Map<MessageId, BdfDictionary> sessions =
new HashMap<MessageId, BdfDictionary>(2);
sessions.put(new MessageId(getRandomId()), new BdfDictionary());
sessions.put(new MessageId(getRandomId()), new BdfDictionary());
testAddingContact(sessions);
}
@Test
public void testRemovingBlogFreshState() throws Exception {
Map<MessageId, BdfDictionary> sessions =
new HashMap<MessageId, BdfDictionary>(0);
testRemovingBlog(sessions);
}
@Test
public void testRemovingBlogExistingState() throws Exception {
Map<MessageId, BdfDictionary> sessions =
new HashMap<MessageId, BdfDictionary>(1);
sessions.put(new MessageId(getRandomId()), new BdfDictionary());
testRemovingBlog(sessions);
}
@Test(expected = DbException.class)
public void testRemovingBlogMultipleSessions() throws Exception {
Map<MessageId, BdfDictionary> sessions =
new HashMap<MessageId, BdfDictionary>(2);
sessions.put(new MessageId(getRandomId()), new BdfDictionary());
sessions.put(new MessageId(getRandomId()), new BdfDictionary());
testRemovingBlog(sessions);
}
private void testAddingContact(final Map<MessageId, BdfDictionary> sessions)
throws Exception {
final Transaction txn = new Transaction(null, false);
final LocalAuthor localAuthor =
new LocalAuthor(localAuthorId, "Local Author",
getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
System.currentTimeMillis());
final BdfDictionary meta = BdfDictionary
.of(new BdfEntry(GROUP_KEY_CONTACT_ID, contactId.getInt()));
final Group localBlogGroup =
new Group(new GroupId(getRandomId()), BlogManager.CLIENT_ID,
getRandomBytes(42));
final Blog localBlog = new Blog(localBlogGroup, localAuthor, false);
context.checking(new Expectations() {{
oneOf(db).getContacts(txn);
will(returnValue(contacts));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
will(returnValue(contactGroup));
oneOf(db).containsGroup(txn, contactGroup.getId());
will(returnValue(false));
oneOf(db).addGroup(txn, contactGroup);
oneOf(db).setGroupVisibility(txn, contactId, contactGroup.getId(),
SHARED);
oneOf(clientHelper)
.mergeGroupMetadata(txn, contactGroup.getId(), meta);
oneOf(identityManager).getLocalAuthor(txn);
will(returnValue(localAuthor));
oneOf(blogManager).getPersonalBlog(localAuthor);
will(returnValue(localBlog));
oneOf(blogManager).getPersonalBlog(author);
will(returnValue(blog));
}});
expectPreShareShareable(txn, contact, localBlog, sessions);
expectPreShareShareable(txn, contact, blog, sessions);
blogSharingManager.createLocalState(txn);
}
private void expectPreShareShareable(final Transaction txn,
final Contact contact, final Blog blog,
final Map<MessageId, BdfDictionary> sessions) throws Exception {
final Group contactGroup =
new Group(new GroupId(getRandomId()), CLIENT_ID,
getRandomBytes(42));
final BdfDictionary sessionDict = new BdfDictionary();
final Message message =
new Message(new MessageId(getRandomId()), contactGroup.getId(),
42L, getRandomBytes(1337));
context.checking(new Expectations() {{
oneOf(contactGroupFactory)
.createContactGroup(CLIENT_ID, contact);
will(returnValue(contactGroup));
oneOf(sessionParser)
.getSessionQuery(new SessionId(blog.getId().getBytes()));
will(returnValue(sessionDict));
oneOf(clientHelper)
.getMessageMetadataAsDictionary(txn, contactGroup.getId(),
sessionDict);
will(returnValue(sessions));
if (sessions.size() == 0) {
oneOf(db).addGroup(txn, blog.getGroup());
oneOf(db).setGroupVisibility(txn, contact.getId(),
blog.getGroup().getId(), SHARED);
oneOf(clientHelper)
.createMessageForStoringMetadata(contactGroup.getId());
will(returnValue(message));
oneOf(db).addLocalMessage(txn, message, new Metadata(), false);
oneOf(sessionEncoder).encodeSession(with(any(Session.class)));
will(returnValue(sessionDict));
oneOf(clientHelper).mergeMessageMetadata(txn, message.getId(),
sessionDict);
}
}});
}
private void testRemovingBlog(final Map<MessageId, BdfDictionary> sessions)
throws Exception {
final Transaction txn = new Transaction(null, false);
final BdfDictionary sessionDict = new BdfDictionary();
final Session session = new Session(contactGroup.getId(), blog.getId());
context.checking(new Expectations() {{
oneOf(db).getContacts(txn);
will(returnValue(contacts));
oneOf(contactGroupFactory).createContactGroup(CLIENT_ID, contact);
will(returnValue(contactGroup));
oneOf(sessionParser)
.getSessionQuery(new SessionId(blog.getId().getBytes()));
will(returnValue(sessionDict));
oneOf(clientHelper)
.getMessageMetadataAsDictionary(txn, contactGroup.getId(),
sessionDict);
will(returnValue(sessions));
if (sessions.size() == 1) {
oneOf(sessionParser)
.parseSession(contactGroup.getId(), sessionDict);
will(returnValue(session));
oneOf(engine).onLeaveAction(txn, session);
will(returnValue(session));
oneOf(sessionEncoder).encodeSession(session);
will(returnValue(sessionDict));
oneOf(clientHelper).mergeMessageMetadata(txn,
sessions.keySet().iterator().next(), sessionDict);
}
}});
blogSharingManager.removingBlog(txn, blog);
}
}