diff --git a/briar-android-tests/src/test/java/org/briarproject/BlogManagerTest.java b/briar-android-tests/src/test/java/org/briarproject/BlogManagerTest.java index 8fd7479f457fc4f331e17d264da2817c782014ce..85803e837e3f0dbd7df0aa0c98fda57954bc0fda 100644 --- a/briar-android-tests/src/test/java/org/briarproject/BlogManagerTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/BlogManagerTest.java @@ -1,147 +1,58 @@ package org.briarproject; -import net.jodah.concurrentunit.Waiter; - import org.briarproject.api.blogs.Blog; import org.briarproject.api.blogs.BlogCommentHeader; -import org.briarproject.api.blogs.BlogFactory; import org.briarproject.api.blogs.BlogManager; import org.briarproject.api.blogs.BlogPost; -import org.briarproject.api.blogs.BlogPostFactory; import org.briarproject.api.blogs.BlogPostHeader; -import org.briarproject.api.contact.ContactId; -import org.briarproject.api.contact.ContactManager; -import org.briarproject.api.crypto.CryptoComponent; -import org.briarproject.api.crypto.SecretKey; import org.briarproject.api.db.DbException; -import org.briarproject.api.event.Event; -import org.briarproject.api.event.EventListener; -import org.briarproject.api.event.MessageStateChangedEvent; -import org.briarproject.api.identity.AuthorFactory; -import org.briarproject.api.identity.IdentityManager; -import org.briarproject.api.identity.LocalAuthor; -import org.briarproject.api.lifecycle.LifecycleManager; -import org.briarproject.api.sync.SyncSession; -import org.briarproject.api.sync.SyncSessionFactory; -import org.briarproject.api.system.Clock; -import org.briarproject.blogs.BlogsModule; -import org.briarproject.contact.ContactModule; -import org.briarproject.crypto.CryptoModule; -import org.briarproject.lifecycle.LifecycleModule; -import org.briarproject.properties.PropertiesModule; -import org.briarproject.sync.SyncModule; -import org.briarproject.transport.TransportModule; -import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; import java.util.Collection; import java.util.Iterator; -import java.util.concurrent.TimeoutException; -import java.util.logging.Logger; - -import javax.inject.Inject; import static junit.framework.Assert.assertFalse; -import static org.briarproject.TestPluginsModule.MAX_LATENCY; import static org.briarproject.api.blogs.MessageType.COMMENT; import static org.briarproject.api.blogs.MessageType.POST; import static org.briarproject.api.blogs.MessageType.WRAPPED_COMMENT; import static org.briarproject.api.blogs.MessageType.WRAPPED_POST; -import static org.briarproject.api.sync.ValidationManager.State.DELIVERED; -import static org.briarproject.api.sync.ValidationManager.State.INVALID; -import static org.briarproject.api.sync.ValidationManager.State.PENDING; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; public class BlogManagerTest extends BriarIntegrationTest { - private LifecycleManager lifecycleManager0, lifecycleManager1; - private SyncSessionFactory sync0, sync1; private BlogManager blogManager0, blogManager1; - private ContactManager contactManager0, contactManager1; - private ContactId contactId0,contactId1; - private IdentityManager identityManager0, identityManager1; - private LocalAuthor author0, author1; private Blog blog0, blog1; - @Inject - Clock clock; - @Inject - AuthorFactory authorFactory; - @Inject - CryptoComponent crypto; - @Inject - BlogFactory blogFactory; - @Inject - BlogPostFactory blogPostFactory; - - // objects accessed from background threads need to be volatile - private volatile Waiter validationWaiter; - private volatile Waiter deliveryWaiter; - - private final File testDir = TestUtils.getTestDirectory(); - private final SecretKey master = TestUtils.getSecretKey(); - private final int TIMEOUT = 15000; - private final String AUTHOR1 = "Author 1"; - private final String AUTHOR2 = "Author 2"; - - private static final Logger LOG = - Logger.getLogger(BlogManagerTest.class.getName()); - - private BlogManagerTestComponent t0, t1; - @Rule public ExpectedException thrown = ExpectedException.none(); @Before + @Override public void setUp() throws Exception { - BlogManagerTestComponent component = - DaggerBlogManagerTestComponent.builder().build(); - component.inject(this); - injectEagerSingletons(component); - - assertTrue(testDir.mkdirs()); - File t0Dir = new File(testDir, AUTHOR1); - t0 = DaggerBlogManagerTestComponent.builder() - .testDatabaseModule(new TestDatabaseModule(t0Dir)).build(); - injectEagerSingletons(t0); - File t1Dir = new File(testDir, AUTHOR2); - t1 = DaggerBlogManagerTestComponent.builder() - .testDatabaseModule(new TestDatabaseModule(t1Dir)).build(); - injectEagerSingletons(t1); - - identityManager0 = t0.getIdentityManager(); - identityManager1 = t1.getIdentityManager(); - contactManager0 = t0.getContactManager(); - contactManager1 = t1.getContactManager(); - blogManager0 = t0.getBlogManager(); - blogManager1 = t1.getBlogManager(); - sync0 = t0.getSyncSessionFactory(); - sync1 = t1.getSyncSessionFactory(); - - // initialize waiters fresh for each test - validationWaiter = new Waiter(); - deliveryWaiter = new Waiter(); + super.setUp(); + + author0 = identityManager0.getLocalAuthor(); + author1 = identityManager1.getLocalAuthor(); + + blogManager0 = c0.getBlogManager(); + blogManager1 = c1.getBlogManager(); + + blog0 = blogFactory.createBlog(author0); + blog1 = blogFactory.createBlog(author1); } @Test public void testPersonalBlogInitialisation() throws Exception { - startLifecycles(); - - defaultInit(); - Collection<Blog> blogs0 = blogManager0.getBlogs(); - assertEquals(2, blogs0.size()); + assertEquals(3, blogs0.size()); Iterator<Blog> i0 = blogs0.iterator(); assertEquals(author0, i0.next().getAuthor()); assertEquals(author1, i0.next().getAuthor()); + assertEquals(author2, i0.next().getAuthor()); Collection<Blog> blogs1 = blogManager1.getBlogs(); assertEquals(2, blogs1.size()); @@ -163,15 +74,10 @@ public class BlogManagerTest extends BriarIntegrationTest { assertEquals(1, blogManager1.getBlogs(author0).size()); assertEquals(1, blogManager0.getBlogs(author1).size()); assertEquals(1, blogManager1.getBlogs(author1).size()); - - stopLifecycles(); } @Test public void testBlogPost() throws Exception { - startLifecycles(); - defaultInit(); - // check that blog0 has no posts final String body = TestUtils.getRandomString(42); Collection<BlogPostHeader> headers0 = @@ -197,8 +103,7 @@ public class BlogManagerTest extends BriarIntegrationTest { assertEquals(0, headers1.size()); // sync the post over - sync0To1(); - deliveryWaiter.await(TIMEOUT, 1); + sync0To1(1, true); // make sure post arrived headers1 = blogManager1.getPostHeaders(blog0.getId()); @@ -207,15 +112,10 @@ public class BlogManagerTest extends BriarIntegrationTest { // check that body is there assertEquals(body, blogManager1.getPostBody(p.getMessage().getId())); - - stopLifecycles(); } @Test public void testBlogPostInWrongBlog() throws Exception { - startLifecycles(); - defaultInit(); - // add a post to blog1 final String body = TestUtils.getRandomString(42); BlogPost p = blogPostFactory @@ -229,22 +129,16 @@ public class BlogManagerTest extends BriarIntegrationTest { assertEquals(1, headers0.size()); // sync the post over - sync0To1(); - validationWaiter.await(TIMEOUT, 1); + sync0To1(1, false); // make sure post did not arrive, because of wrong signature Collection<BlogPostHeader> headers1 = blogManager1.getPostHeaders(blog1.getId()); assertEquals(0, headers1.size()); - - stopLifecycles(); } @Test public void testCanNotRemoveContactsPersonalBlog() throws Exception { - startLifecycles(); - defaultInit(); - assertFalse(blogManager0.canBeRemoved(blog1.getId())); assertFalse(blogManager1.canBeRemoved(blog0.getId())); @@ -257,15 +151,10 @@ public class BlogManagerTest extends BriarIntegrationTest { // blogs have not been removed assertEquals(2, blogManager0.getBlogs().size()); assertEquals(2, blogManager1.getBlogs().size()); - - stopLifecycles(); } @Test public void testBlogComment() throws Exception { - startLifecycles(); - defaultInit(); - // add a post to blog0 final String body = TestUtils.getRandomString(42); BlogPost p = blogPostFactory @@ -274,8 +163,7 @@ public class BlogManagerTest extends BriarIntegrationTest { blogManager0.addLocalPost(p); // sync the post over - sync0To1(); - deliveryWaiter.await(TIMEOUT, 1); + sync0To1(1, true); // make sure post arrived Collection<BlogPostHeader> headers1 = @@ -290,8 +178,7 @@ public class BlogManagerTest extends BriarIntegrationTest { headers1.iterator().next()); // sync comment over - sync1To0(); - deliveryWaiter.await(TIMEOUT, 2); + sync1To0(2, true); // make sure comment and wrapped post arrived Collection<BlogPostHeader> headers0 = @@ -307,15 +194,10 @@ public class BlogManagerTest extends BriarIntegrationTest { // 1 has only their own comment in their blog headers1 = blogManager1.getPostHeaders(blog1.getId()); assertEquals(1, headers1.size()); - - stopLifecycles(); } @Test public void testBlogCommentOnOwnPost() throws Exception { - startLifecycles(); - defaultInit(); - // add a post to blog0 final String body = TestUtils.getRandomString(42); BlogPost p = blogPostFactory @@ -335,8 +217,7 @@ public class BlogManagerTest extends BriarIntegrationTest { .addLocalComment(author0, blog0.getId(), comment, header); // sync the post and comment over - sync0To1(); - deliveryWaiter.await(TIMEOUT, 2); + sync0To1(2, true); // make sure post arrived Collection<BlogPostHeader> headers1 = @@ -349,15 +230,10 @@ public class BlogManagerTest extends BriarIntegrationTest { assertEquals(comment, ((BlogCommentHeader)h).getComment()); } } - - stopLifecycles(); } @Test public void testCommentOnComment() throws Exception { - startLifecycles(); - defaultInit(); - // add a post to blog0 final String body = TestUtils.getRandomString(42); BlogPost p = blogPostFactory @@ -366,8 +242,7 @@ public class BlogManagerTest extends BriarIntegrationTest { blogManager0.addLocalPost(p); // sync the post over - sync0To1(); - deliveryWaiter.await(TIMEOUT, 1); + sync0To1(1, true); // make sure post arrived Collection<BlogPostHeader> headers1 = @@ -381,8 +256,7 @@ public class BlogManagerTest extends BriarIntegrationTest { headers1.iterator().next()); // sync comment over - sync1To0(); - deliveryWaiter.await(TIMEOUT, 2); + sync1To0(2, true); // make sure comment and wrapped post arrived Collection<BlogPostHeader> headers0 = @@ -399,8 +273,7 @@ public class BlogManagerTest extends BriarIntegrationTest { .addLocalComment(author0, blog0.getId(), comment, cHeader); // sync comment over - sync0To1(); - deliveryWaiter.await(TIMEOUT, 3); + sync0To1(3, true); // check that comment arrived headers1 = @@ -421,8 +294,7 @@ public class BlogManagerTest extends BriarIntegrationTest { blogManager1.addLocalComment(author1, blog1.getId(), comment2, cHeader); // sync comment over - sync1To0(); - deliveryWaiter.await(TIMEOUT, 4); + sync1To0(4, true); // make sure new comment arrived headers0 = @@ -448,16 +320,10 @@ public class BlogManagerTest extends BriarIntegrationTest { } } assertTrue(satisfied); - - stopLifecycles(); } @Test public void testCommentOnOwnComment() throws Exception { - - startLifecycles(); - defaultInit(); - // add a post to blog0 final String body = TestUtils.getRandomString(42); BlogPost p = blogPostFactory @@ -466,8 +332,7 @@ public class BlogManagerTest extends BriarIntegrationTest { blogManager0.addLocalPost(p); // sync the post over - sync0To1(); - deliveryWaiter.await(TIMEOUT, 1); + sync0To1(1, true); // make sure post arrived Collection<BlogPostHeader> headers1 = @@ -492,128 +357,12 @@ public class BlogManagerTest extends BriarIntegrationTest { blogManager1.addLocalComment(author1, blog1.getId(), comment, ch); // sync both comments over (2 comments + 1 wrapped post) - sync1To0(); - deliveryWaiter.await(TIMEOUT, 3); + sync1To0(3, true); // make sure both comments arrived Collection<BlogPostHeader> headers0 = blogManager0.getPostHeaders(blog1.getId()); assertEquals(2, headers0.size()); - - stopLifecycles(); - } - - @After - public void tearDown() throws Exception { - TestUtils.deleteTestDirectory(testDir); - } - - private class Listener implements EventListener { - @Override - public void eventOccurred(Event e) { - if (e instanceof MessageStateChangedEvent) { - MessageStateChangedEvent event = (MessageStateChangedEvent) e; - if (!event.isLocal()) { - if (event.getState() == DELIVERED) { - deliveryWaiter.resume(); - } else if (event.getState() == INVALID || - event.getState() == PENDING) { - validationWaiter.resume(); - } - } - } - } - } - - private void defaultInit() throws DbException { - getDefaultIdentities(); - addDefaultContacts(); - listenToEvents(); - } - - private void getDefaultIdentities() throws DbException { - author0 = identityManager0.getLocalAuthor(); - author1 = identityManager1.getLocalAuthor(); - blog0 = blogFactory.createBlog(author0); - blog1 = blogFactory.createBlog(author1); - } - - private void addDefaultContacts() throws DbException { - // sharer adds invitee as contact - contactId1 = contactManager0.addContact(author1, - author0.getId(), master, clock.currentTimeMillis(), true, - true, true - ); - // invitee adds sharer back - contactId0 = contactManager1.addContact(author0, - author1.getId(), master, clock.currentTimeMillis(), true, - true, true - ); - } - - private void listenToEvents() { - Listener listener0 = new Listener(); - t0.getEventBus().addListener(listener0); - Listener listener1 = new Listener(); - t1.getEventBus().addListener(listener1); - } - - private void sync0To1() throws IOException, TimeoutException { - deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1"); - } - - private void sync1To0() throws IOException, TimeoutException { - deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0"); - } - - private void deliverMessage(SyncSessionFactory fromSync, ContactId fromId, - SyncSessionFactory toSync, ContactId toId, String debug) - throws IOException, TimeoutException { - - if (debug != null) LOG.info("TEST: Sending message from " + debug); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - // Create an outgoing sync session - SyncSession sessionFrom = - fromSync.createSimplexOutgoingSession(toId, MAX_LATENCY, out); - // Write whatever needs to be written - sessionFrom.run(); - out.close(); - - ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); - // Create an incoming sync session - SyncSession sessionTo = toSync.createIncomingSession(fromId, in); - // Read whatever needs to be read - sessionTo.run(); - in.close(); - } - - private void startLifecycles() throws InterruptedException { - // Start the lifecycle manager and wait for it to finish - lifecycleManager0 = t0.getLifecycleManager(); - lifecycleManager1 = t1.getLifecycleManager(); - lifecycleManager0.startServices(AUTHOR1); - lifecycleManager1.startServices(AUTHOR2); - lifecycleManager0.waitForStartup(); - lifecycleManager1.waitForStartup(); - } - - private void stopLifecycles() throws InterruptedException { - // Clean up - lifecycleManager0.stopServices(); - lifecycleManager1.stopServices(); - lifecycleManager0.waitForShutdown(); - lifecycleManager1.waitForShutdown(); - } - - private void injectEagerSingletons(BlogManagerTestComponent component) { - component.inject(new LifecycleModule.EagerSingletons()); - component.inject(new BlogsModule.EagerSingletons()); - component.inject(new CryptoModule.EagerSingletons()); - component.inject(new ContactModule.EagerSingletons()); - component.inject(new TransportModule.EagerSingletons()); - component.inject(new SyncModule.EagerSingletons()); - component.inject(new PropertiesModule.EagerSingletons()); } } diff --git a/briar-android-tests/src/test/java/org/briarproject/BlogManagerTestComponent.java b/briar-android-tests/src/test/java/org/briarproject/BlogManagerTestComponent.java deleted file mode 100644 index 41d15eb9e660ce8e94cf9840aee2f1ce4a97700d..0000000000000000000000000000000000000000 --- a/briar-android-tests/src/test/java/org/briarproject/BlogManagerTestComponent.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.briarproject; - -import org.briarproject.api.blogs.BlogManager; -import org.briarproject.api.contact.ContactManager; -import org.briarproject.api.event.EventBus; -import org.briarproject.api.identity.IdentityManager; -import org.briarproject.api.lifecycle.LifecycleManager; -import org.briarproject.api.sync.SyncSessionFactory; -import org.briarproject.blogs.BlogsModule; -import org.briarproject.clients.ClientsModule; -import org.briarproject.contact.ContactModule; -import org.briarproject.crypto.CryptoModule; -import org.briarproject.data.DataModule; -import org.briarproject.db.DatabaseModule; -import org.briarproject.event.EventModule; -import org.briarproject.identity.IdentityModule; -import org.briarproject.lifecycle.LifecycleModule; -import org.briarproject.properties.PropertiesModule; -import org.briarproject.sharing.SharingModule; -import org.briarproject.sync.SyncModule; -import org.briarproject.system.SystemModule; -import org.briarproject.transport.TransportModule; - -import javax.inject.Singleton; - -import dagger.Component; - -@Singleton -@Component(modules = { - TestDatabaseModule.class, - TestPluginsModule.class, - TestSeedProviderModule.class, - ClientsModule.class, - ContactModule.class, - CryptoModule.class, - DataModule.class, - DatabaseModule.class, - EventModule.class, - BlogsModule.class, - IdentityModule.class, - LifecycleModule.class, - PropertiesModule.class, - SharingModule.class, - SyncModule.class, - SystemModule.class, - TransportModule.class -}) -interface BlogManagerTestComponent { - - void inject(BlogManagerTest testCase); - - void inject(ContactModule.EagerSingletons init); - - void inject(CryptoModule.EagerSingletons init); - - void inject(BlogsModule.EagerSingletons init); - - void inject(LifecycleModule.EagerSingletons init); - - void inject(PropertiesModule.EagerSingletons init); - - void inject(SyncModule.EagerSingletons init); - - void inject(TransportModule.EagerSingletons init); - - LifecycleManager getLifecycleManager(); - - EventBus getEventBus(); - - IdentityManager getIdentityManager(); - - ContactManager getContactManager(); - - BlogManager getBlogManager(); - - SyncSessionFactory getSyncSessionFactory(); - -} diff --git a/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java index 4f47c3444ad8bacf7f7dc57dfad82725ee8664f1..2ceea6e9f2a9e28464e91db1f579c0009d98c924 100644 --- a/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTest.java @@ -6,206 +6,114 @@ import org.briarproject.api.blogs.Blog; import org.briarproject.api.blogs.BlogInvitationRequest; import org.briarproject.api.blogs.BlogInvitationResponse; import org.briarproject.api.blogs.BlogManager; -import org.briarproject.api.blogs.BlogPostFactory; import org.briarproject.api.blogs.BlogSharingManager; -import org.briarproject.api.clients.ContactGroupFactory; -import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.contact.Contact; -import org.briarproject.api.contact.ContactId; -import org.briarproject.api.contact.ContactManager; -import org.briarproject.api.crypto.CryptoComponent; -import org.briarproject.api.crypto.SecretKey; import org.briarproject.api.db.DbException; import org.briarproject.api.event.BlogInvitationReceivedEvent; import org.briarproject.api.event.BlogInvitationResponseReceivedEvent; import org.briarproject.api.event.Event; import org.briarproject.api.event.EventListener; -import org.briarproject.api.event.MessageStateChangedEvent; -import org.briarproject.api.identity.AuthorFactory; -import org.briarproject.api.identity.IdentityManager; -import org.briarproject.api.identity.LocalAuthor; -import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.sharing.InvitationMessage; import org.briarproject.api.sync.GroupId; -import org.briarproject.api.sync.SyncSession; -import org.briarproject.api.sync.SyncSessionFactory; -import org.briarproject.api.sync.ValidationManager.State; -import org.briarproject.api.system.Clock; -import org.briarproject.blogs.BlogsModule; -import org.briarproject.contact.ContactModule; -import org.briarproject.crypto.CryptoModule; -import org.briarproject.lifecycle.LifecycleModule; -import org.briarproject.properties.PropertiesModule; -import org.briarproject.sharing.SharingModule; -import org.briarproject.sync.SyncModule; -import org.briarproject.transport.TransportModule; -import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.concurrent.TimeoutException; -import java.util.logging.Logger; -import javax.inject.Inject; - -import static org.briarproject.TestPluginsModule.MAX_LATENCY; +import static org.briarproject.TestUtils.assertGroupCount; import static org.briarproject.api.blogs.BlogSharingManager.CLIENT_ID; -import static org.briarproject.api.sync.ValidationManager.State.DELIVERED; -import static org.briarproject.api.sync.ValidationManager.State.INVALID; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class BlogSharingIntegrationTest extends BriarIntegrationTest { - private LifecycleManager lifecycleManager0, lifecycleManager1, - lifecycleManager2; - private SyncSessionFactory sync0, sync1; - private BlogManager blogManager0, blogManager1; - private MessageTracker messageTracker0, messageTracker1; - private ContactManager contactManager0, contactManager1, contactManager2; - private Contact contact1, contact2, contact01, contact02; - private ContactId contactId1, contactId01; - private IdentityManager identityManager0, identityManager1, - identityManager2; - private LocalAuthor author0, author1, author2; + private BlogManager blogManager1; private Blog blog0, blog1, blog2; private SharerListener listener0; private InviteeListener listener1; - @Inject - Clock clock; - @Inject - AuthorFactory authorFactory; - @Inject - ContactGroupFactory contactGroupFactory; - @Inject - BlogPostFactory blogPostFactory; - @Inject - CryptoComponent cryptoComponent; - // objects accessed from background threads need to be volatile private volatile BlogSharingManager blogSharingManager0; private volatile BlogSharingManager blogSharingManager1; private volatile BlogSharingManager blogSharingManager2; private volatile Waiter eventWaiter; - private volatile Waiter msgWaiter; - - private final File testDir = TestUtils.getTestDirectory(); - private final SecretKey master = TestUtils.getSecretKey(); - private final int TIMEOUT = 15000; - private final String SHARER = "Sharer"; - private final String INVITEE = "Invitee"; - private final String CONTACT2 = "Contact2"; - - private static final Logger LOG = - Logger.getLogger(BlogSharingIntegrationTest.class.getName()); - - private BlogSharingIntegrationTestComponent t0, t1, t2; @Rule public ExpectedException thrown = ExpectedException.none(); @Before - public void setUp() { - BlogSharingIntegrationTestComponent component = - DaggerBlogSharingIntegrationTestComponent.builder().build(); - component.inject(this); - injectEagerSingletons(component); - - assertTrue(testDir.mkdirs()); - File t0Dir = new File(testDir, SHARER); - t0 = DaggerBlogSharingIntegrationTestComponent.builder() - .testDatabaseModule(new TestDatabaseModule(t0Dir)).build(); - injectEagerSingletons(t0); - File t1Dir = new File(testDir, INVITEE); - t1 = DaggerBlogSharingIntegrationTestComponent.builder() - .testDatabaseModule(new TestDatabaseModule(t1Dir)).build(); - injectEagerSingletons(t1); - File t2Dir = new File(testDir, CONTACT2); - t2 = DaggerBlogSharingIntegrationTestComponent.builder() - .testDatabaseModule(new TestDatabaseModule(t2Dir)).build(); - injectEagerSingletons(t2); - - identityManager0 = t0.getIdentityManager(); - identityManager1 = t1.getIdentityManager(); - identityManager2 = t2.getIdentityManager(); - contactManager0 = t0.getContactManager(); - contactManager1 = t1.getContactManager(); - contactManager2 = t2.getContactManager(); - blogManager0 = t0.getBlogManager(); - blogManager1 = t1.getBlogManager(); - messageTracker0 = t0.getMessageTracker(); - messageTracker1 = t1.getMessageTracker(); - blogSharingManager0 = t0.getBlogSharingManager(); - blogSharingManager1 = t1.getBlogSharingManager(); - blogSharingManager2 = t2.getBlogSharingManager(); - sync0 = t0.getSyncSessionFactory(); - sync1 = t1.getSyncSessionFactory(); + @Override + public void setUp() throws Exception { + super.setUp(); + + BlogManager blogManager0 = c0.getBlogManager(); + blogManager1 = c1.getBlogManager(); + blogSharingManager0 = c0.getBlogSharingManager(); + blogSharingManager1 = c1.getBlogSharingManager(); + blogSharingManager2 = c2.getBlogSharingManager(); + + blog0 = blogManager0.getPersonalBlog(author0); + blog1 = blogManager0.getPersonalBlog(author1); + blog2 = blogManager0.getPersonalBlog(author2); // initialize waiters fresh for each test eventWaiter = new Waiter(); - msgWaiter = new Waiter(); } @Test public void testPersonalBlogCannotBeSharedWithOwner() throws Exception { - startLifecycles(); - defaultInit(true); + listenToEvents(true); - assertFalse(blogSharingManager0.canBeShared(blog1.getId(), contact1)); - assertFalse(blogSharingManager0.canBeShared(blog2.getId(), contact2)); - assertFalse(blogSharingManager1.canBeShared(blog0.getId(), contact01)); - assertFalse(blogSharingManager2.canBeShared(blog0.getId(), contact02)); + assertFalse(blogSharingManager0.canBeShared(blog1.getId(), + contact1From0)); + assertFalse(blogSharingManager0.canBeShared(blog2.getId(), + contact2From0)); + assertFalse(blogSharingManager1.canBeShared(blog0.getId(), + contact0From1)); + assertFalse(blogSharingManager2.canBeShared(blog0.getId(), + contact0From2)); // create invitation blogSharingManager0 - .sendInvitation(blog1.getId(), contactId1, "Hi!"); + .sendInvitation(blog1.getId(), contactId1From0, "Hi!"); // sync invitation - sync0To1(); + sync0To1(1, false); // make sure the invitee ignored the request for their own blog assertFalse(listener1.requestReceived); - - stopLifecycles(); } @Test public void testSuccessfulSharing() throws Exception { - startLifecycles(); - // initialize and let invitee accept all requests - defaultInit(true); + listenToEvents(true); // send invitation blogSharingManager0 - .sendInvitation(blog2.getId(), contactId1, "Hi!"); + .sendInvitation(blog2.getId(), contactId1From0, "Hi!"); // invitee has own blog and that of the sharer assertEquals(2, blogManager1.getBlogs().size()); // get sharing group and assert group message count - GroupId g = contactGroupFactory.createContactGroup(CLIENT_ID, contact1) + GroupId g = contactGroupFactory.createContactGroup(CLIENT_ID, + contact1From0) .getId(); assertGroupCount(messageTracker0, g, 1, 0); // sync first request message - sync0To1(); + sync0To1(1, true); eventWaiter.await(TIMEOUT, 1); assertTrue(listener1.requestReceived); assertGroupCount(messageTracker1, g, 2, 1); // sync response back - sync1To0(); + sync1To0(1, true); eventWaiter.await(TIMEOUT, 1); assertTrue(listener0.responseReceived); assertGroupCount(messageTracker0, g, 2, 1); @@ -217,7 +125,7 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { // invitee has one invitation message from sharer List<InvitationMessage> list = new ArrayList<>(blogSharingManager1 - .getInvitationMessages(contactId01)); + .getInvitationMessages(contactId0From1)); assertEquals(2, list.size()); // check other things are alright with the message for (InvitationMessage m : list) { @@ -227,49 +135,47 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { assertFalse(invitation.isAvailable()); assertEquals(blog2.getAuthor().getName(), invitation.getBlogAuthorName()); - assertEquals(contactId1, invitation.getContactId()); + assertEquals(contactId1From0, invitation.getContactId()); assertEquals("Hi!", invitation.getMessage()); } else { BlogInvitationResponse response = (BlogInvitationResponse) m; - assertEquals(contactId01, response.getContactId()); + assertEquals(contactId0From1, response.getContactId()); assertTrue(response.wasAccepted()); assertTrue(response.isLocal()); } } // sharer has own invitation message and response assertEquals(2, - blogSharingManager0.getInvitationMessages(contactId1) + blogSharingManager0.getInvitationMessages(contactId1From0) .size()); // blog can not be shared again - assertFalse(blogSharingManager0.canBeShared(blog2.getId(), contact1)); - assertFalse(blogSharingManager1.canBeShared(blog2.getId(), contact01)); + assertFalse(blogSharingManager0.canBeShared(blog2.getId(), + contact1From0)); + assertFalse(blogSharingManager1.canBeShared(blog2.getId(), + contact0From1)); // group message count is still correct assertGroupCount(messageTracker0, g, 2, 1); assertGroupCount(messageTracker1, g, 2, 1); - - stopLifecycles(); } @Test public void testDeclinedSharing() throws Exception { - startLifecycles(); - // initialize and let invitee deny all requests - defaultInit(false); + listenToEvents(false); // send invitation blogSharingManager0 - .sendInvitation(blog2.getId(), contactId1, null); + .sendInvitation(blog2.getId(), contactId1From0, null); // sync first request message - sync0To1(); + sync0To1(1, true); eventWaiter.await(TIMEOUT, 1); assertTrue(listener1.requestReceived); // sync response back - sync1To0(); + sync1To0(1, true); eventWaiter.await(TIMEOUT, 1); assertTrue(listener0.responseReceived); @@ -282,7 +188,7 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { // invitee has one invitation message from sharer and one response List<InvitationMessage> list = new ArrayList<>(blogSharingManager1 - .getInvitationMessages(contactId01)); + .getInvitationMessages(contactId0From1)); assertEquals(2, list.size()); // check things are alright with the message for (InvitationMessage m : list) { @@ -292,44 +198,40 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { assertFalse(invitation.isAvailable()); assertEquals(blog2.getAuthor().getName(), invitation.getBlogAuthorName()); - assertEquals(contactId1, invitation.getContactId()); + assertEquals(contactId1From0, invitation.getContactId()); assertEquals(null, invitation.getMessage()); } else { BlogInvitationResponse response = (BlogInvitationResponse) m; - assertEquals(contactId01, response.getContactId()); + assertEquals(contactId0From1, response.getContactId()); assertFalse(response.wasAccepted()); assertTrue(response.isLocal()); } } // sharer has own invitation message and response assertEquals(2, - blogSharingManager0.getInvitationMessages(contactId1) + blogSharingManager0.getInvitationMessages(contactId1From0) .size()); // blog can be shared again - assertTrue(blogSharingManager0.canBeShared(blog2.getId(), contact1)); - - stopLifecycles(); + assertTrue(blogSharingManager0.canBeShared(blog2.getId(), contact1From0)); } @Test public void testInviteeLeavesAfterFinished() throws Exception { - startLifecycles(); - // initialize and let invitee accept all requests - defaultInit(true); + listenToEvents(true); // send invitation blogSharingManager0 - .sendInvitation(blog2.getId(), contactId1, "Hi!"); + .sendInvitation(blog2.getId(), contactId1From0, "Hi!"); // sync first request message - sync0To1(); + sync0To1(1, true); eventWaiter.await(TIMEOUT, 1); assertTrue(listener1.requestReceived); // sync response back - sync1To0(); + sync1To0(1, true); eventWaiter.await(TIMEOUT, 1); assertTrue(listener0.responseReceived); @@ -340,16 +242,16 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { // sharer shares blog with invitee assertTrue(blogSharingManager0.getSharedWith(blog2.getId()) - .contains(contact1)); + .contains(contact1From0)); // invitee gets blog shared by sharer assertTrue(blogSharingManager1.getSharedBy(blog2.getId()) - .contains(contact01)); + .contains(contact0From1)); // invitee un-subscribes from blog blogManager1.removeBlog(blog2); // send leave message to sharer - sync1To0(); + sync1To0(1, true); // blog is gone assertEquals(0, blogSharingManager0.getInvitations().size()); @@ -357,41 +259,30 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { // sharer no longer shares blog with invitee assertFalse(blogSharingManager0.getSharedWith(blog2.getId()) - .contains(contact1)); + .contains(contact1From0)); // invitee no longer gets blog shared by sharer assertFalse(blogSharingManager1.getSharedBy(blog2.getId()) - .contains(contact01)); + .contains(contact0From1)); // blog can be shared again - assertTrue(blogSharingManager0.canBeShared(blog2.getId(), contact1)); - assertTrue(blogSharingManager1.canBeShared(blog2.getId(), contact01)); - - stopLifecycles(); + assertTrue(blogSharingManager0.canBeShared(blog2.getId(), contact1From0)); + assertTrue(blogSharingManager1.canBeShared(blog2.getId(), contact0From1)); } @Test public void testInvitationForExistingBlog() throws Exception { - startLifecycles(); - // initialize and let invitee accept all requests - defaultInit(true); + listenToEvents(true); // 1 and 2 are adding each other - contactManager1.addContact(author2, - author1.getId(), master, clock.currentTimeMillis(), true, - true, true - ); - contactManager2.addContact(author1, - author2.getId(), master, clock.currentTimeMillis(), true, - true, true - ); + addContacts1And2(); assertEquals(3, blogManager1.getBlogs().size()); // sharer sends invitation for 2's blog to 1 blogSharingManager0 - .sendInvitation(blog2.getId(), contactId1, "Hi!"); + .sendInvitation(blog2.getId(), contactId1From0, "Hi!"); // sync first request message - sync0To1(); + sync0To1(1, true); eventWaiter.await(TIMEOUT, 1); assertTrue(listener1.requestReceived); @@ -399,44 +290,40 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { Collection<Contact> contacts = blogSharingManager1.getSharedBy(blog2.getId()); assertEquals(1, contacts.size()); - assertTrue(contacts.contains(contact01)); + assertTrue(contacts.contains(contact0From1)); // make sure 1 knows that they have blog2 already Collection<InvitationMessage> messages = - blogSharingManager1.getInvitationMessages(contactId01); + blogSharingManager1.getInvitationMessages(contactId0From1); assertEquals(2, messages.size()); assertEquals(blog2, blogManager1.getBlog(blog2.getId())); // sync response back - sync1To0(); + sync1To0(1, true); eventWaiter.await(TIMEOUT, 1); assertTrue(listener0.responseReceived); // blog was not added, because it was there already assertEquals(0, blogSharingManager0.getInvitations().size()); assertEquals(3, blogManager1.getBlogs().size()); - - stopLifecycles(); } @Test public void testRemovingSharedBlog() throws Exception { - startLifecycles(); - // initialize and let invitee accept all requests - defaultInit(true); + listenToEvents(true); // send invitation blogSharingManager0 - .sendInvitation(blog2.getId(), contactId1, "Hi!"); + .sendInvitation(blog2.getId(), contactId1From0, "Hi!"); // sync first request message - sync0To1(); + sync0To1(1, true); eventWaiter.await(TIMEOUT, 1); assertTrue(listener1.requestReceived); // sync response back - sync1To0(); + sync1To0(1, true); eventWaiter.await(TIMEOUT, 1); assertTrue(listener0.responseReceived); @@ -445,11 +332,11 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { Collection<Contact> sharedWith = blogSharingManager0.getSharedWith(blog2.getId()); assertEquals(1, sharedWith.size()); - assertEquals(contact1, sharedWith.iterator().next()); + assertEquals(contact1From0, sharedWith.iterator().next()); Collection<Contact> sharedBy = blogSharingManager1.getSharedBy(blog2.getId()); assertEquals(1, sharedBy.size()); - assertEquals(contact01, sharedBy.iterator().next()); + assertEquals(contact0From1, sharedBy.iterator().next()); // shared blog can be removed assertTrue(blogManager1.canBeRemoved(blog2.getId())); @@ -458,32 +345,28 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { blogManager1.removeBlog(blog2); // sync LEAVE message - sync1To0(); + sync1To0(1, true); // sharer does not share this blog anymore with invitee sharedWith = blogSharingManager0.getSharedWith(blog2.getId()); assertEquals(0, sharedWith.size()); - - stopLifecycles(); } @Test public void testSharedBlogBecomesPermanent() throws Exception { - startLifecycles(); - - // initialize and let invitee accept all requests - defaultInit(true); + // let invitee accept all requests + listenToEvents(true); // invitee only sees two blogs assertEquals(2, blogManager1.getBlogs().size()); // sharer sends invitation for 2's blog to 1 blogSharingManager0 - .sendInvitation(blog2.getId(), contactId1, "Hi!"); + .sendInvitation(blog2.getId(), contactId1From0, "Hi!"); // sync first request message - sync0To1(); + sync0To1(1, true); eventWaiter.await(TIMEOUT, 1); assertTrue(listener1.requestReceived); @@ -491,10 +374,10 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { Collection<Contact> contacts = blogSharingManager1.getSharedBy(blog2.getId()); assertEquals(1, contacts.size()); - assertTrue(contacts.contains(contact01)); + assertTrue(contacts.contains(contact0From1)); // sync response back - sync1To0(); + sync1To0(1, true); eventWaiter.await(TIMEOUT, 1); assertTrue(listener0.responseReceived); @@ -503,26 +386,11 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { assertTrue(blogManager1.canBeRemoved(blog2.getId())); // 1 and 2 are adding each other - contactManager1.addContact(author2, - author1.getId(), master, clock.currentTimeMillis(), true, - true, true - ); - contactManager2.addContact(author1, - author2.getId(), master, clock.currentTimeMillis(), true, - true, true - ); + addContacts1And2(); assertEquals(3, blogManager1.getBlogs().size()); // now blog can not be removed anymore assertFalse(blogManager1.canBeRemoved(blog2.getId())); - - stopLifecycles(); - } - - - @After - public void tearDown() throws InterruptedException { - TestUtils.deleteTestDirectory(testDir); } private class SharerListener implements EventListener { @@ -531,17 +399,10 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { @Override public void eventOccurred(Event e) { - if (e instanceof MessageStateChangedEvent) { - MessageStateChangedEvent event = (MessageStateChangedEvent) e; - State s = event.getState(); - if ((s == DELIVERED || s == INVALID) && !event.isLocal()) { - LOG.info("TEST: Sharer received message"); - msgWaiter.resume(); - } - } else if (e instanceof BlogInvitationResponseReceivedEvent) { + if (e instanceof BlogInvitationResponseReceivedEvent) { BlogInvitationResponseReceivedEvent event = (BlogInvitationResponseReceivedEvent) e; - eventWaiter.assertEquals(contactId1, event.getContactId()); + eventWaiter.assertEquals(contactId1From0, event.getContactId()); responseReceived = true; eventWaiter.resume(); } @@ -549,10 +410,10 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { else if (e instanceof BlogInvitationReceivedEvent) { BlogInvitationReceivedEvent event = (BlogInvitationReceivedEvent) e; - eventWaiter.assertEquals(contactId1, event.getContactId()); + eventWaiter.assertEquals(contactId1From0, event.getContactId()); Blog b = event.getShareable(); try { - Contact c = contactManager0.getContact(contactId1); + Contact c = contactManager0.getContact(contactId1From0); blogSharingManager0.respondToInvitation(b, c, true); } catch (DbException ex) { eventWaiter.rethrow(ex); @@ -580,14 +441,7 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { @Override public void eventOccurred(Event e) { - if (e instanceof MessageStateChangedEvent) { - MessageStateChangedEvent event = (MessageStateChangedEvent) e; - State s = event.getState(); - if ((s == DELIVERED || s == INVALID) && !event.isLocal()) { - LOG.info("TEST: Invitee received message"); - msgWaiter.resume(); - } - } else if (e instanceof BlogInvitationReceivedEvent) { + if (e instanceof BlogInvitationReceivedEvent) { BlogInvitationReceivedEvent event = (BlogInvitationReceivedEvent) e; requestReceived = true; @@ -609,135 +463,19 @@ public class BlogSharingIntegrationTest extends BriarIntegrationTest { else if (e instanceof BlogInvitationResponseReceivedEvent) { BlogInvitationResponseReceivedEvent event = (BlogInvitationResponseReceivedEvent) e; - eventWaiter.assertEquals(contactId01, event.getContactId()); + eventWaiter.assertEquals(contactId0From1, event.getContactId()); eventWaiter.resume(); } } } - private void startLifecycles() throws InterruptedException { - // Start the lifecycle manager and wait for it to finish - lifecycleManager0 = t0.getLifecycleManager(); - lifecycleManager1 = t1.getLifecycleManager(); - lifecycleManager2 = t2.getLifecycleManager(); - lifecycleManager0.startServices(SHARER); - lifecycleManager1.startServices(INVITEE); - lifecycleManager2.startServices(CONTACT2); - lifecycleManager0.waitForStartup(); - lifecycleManager1.waitForStartup(); - lifecycleManager2.waitForStartup(); - } - - private void stopLifecycles() throws InterruptedException { - // Clean up - lifecycleManager0.stopServices(); - lifecycleManager1.stopServices(); - lifecycleManager2.stopServices(); - lifecycleManager0.waitForShutdown(); - lifecycleManager1.waitForShutdown(); - lifecycleManager2.waitForShutdown(); - } - - private void defaultInit(boolean accept) throws DbException { - getDefaultIdentities(); - addDefaultContacts(); - getPersonalBlogOfSharer(); - listenToEvents(accept); - } - - private void getDefaultIdentities() throws DbException { - author0 = identityManager0.getLocalAuthor(); - author1 = identityManager1.getLocalAuthor(); - author2 = identityManager2.getLocalAuthor(); - } - - private void addDefaultContacts() throws DbException { - // sharer adds invitee as contact - contactId1 = contactManager0.addContact(author1, - author0.getId(), master, clock.currentTimeMillis(), true, - true, true - ); - contact1 = contactManager0.getContact(contactId1); - // sharer adds second contact - ContactId contactId2 = contactManager0.addContact(author2, - author0.getId(), master, clock.currentTimeMillis(), true, - true, true - ); - contact2 = contactManager0.getContact(contactId2); - // contacts add sharer back - contactId01 = contactManager1.addContact(author0, - author1.getId(), master, clock.currentTimeMillis(), true, - true, true - ); - contact01 = contactManager1.getContact(contactId01); - ContactId contactId02 = contactManager2.addContact(author0, - author2.getId(), master, clock.currentTimeMillis(), true, - true, true - ); - contact02 = contactManager2.getContact(contactId02); - } - - private void getPersonalBlogOfSharer() throws DbException { - blog0 = blogManager0.getPersonalBlog(author0); - blog1 = blogManager0.getPersonalBlog(author1); - blog2 = blogManager0.getPersonalBlog(author2); - } - - private void listenToEvents(boolean accept) { + private void listenToEvents(boolean accept) throws DbException { listener0 = new SharerListener(); - t0.getEventBus().addListener(listener0); + c0.getEventBus().addListener(listener0); listener1 = new InviteeListener(accept); - t1.getEventBus().addListener(listener1); + c1.getEventBus().addListener(listener1); SharerListener listener2 = new SharerListener(); - t2.getEventBus().addListener(listener2); - } - - private void sync0To1() throws IOException, TimeoutException { - deliverMessage(sync0, contactId01, sync1, contactId1, - "Sharer to Invitee"); - } - - private void sync1To0() throws IOException, TimeoutException { - deliverMessage(sync1, contactId1, sync0, contactId01, - "Invitee to Sharer"); - } - - private void deliverMessage(SyncSessionFactory fromSync, ContactId fromId, - SyncSessionFactory toSync, ContactId toId, String debug) - throws IOException, TimeoutException { - - if (debug != null) LOG.info("TEST: Sending message from " + debug); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - // Create an outgoing sync session - SyncSession sessionFrom = - fromSync.createSimplexOutgoingSession(toId, MAX_LATENCY, out); - // Write whatever needs to be written - sessionFrom.run(); - out.close(); - - ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); - // Create an incoming sync session - SyncSession sessionTo = toSync.createIncomingSession(fromId, in); - // Read whatever needs to be read - sessionTo.run(); - in.close(); - - // wait for message to actually arrive - msgWaiter.await(TIMEOUT, 1); - } - - private void injectEagerSingletons( - BlogSharingIntegrationTestComponent component) { - - component.inject(new LifecycleModule.EagerSingletons()); - component.inject(new BlogsModule.EagerSingletons()); - component.inject(new CryptoModule.EagerSingletons()); - component.inject(new ContactModule.EagerSingletons()); - component.inject(new TransportModule.EagerSingletons()); - component.inject(new SharingModule.EagerSingletons()); - component.inject(new SyncModule.EagerSingletons()); - component.inject(new PropertiesModule.EagerSingletons()); + c2.getEventBus().addListener(listener2); } } diff --git a/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTestComponent.java b/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTestComponent.java deleted file mode 100644 index d1cde03d4242cb388436625bb01112914b79661f..0000000000000000000000000000000000000000 --- a/briar-android-tests/src/test/java/org/briarproject/BlogSharingIntegrationTestComponent.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.briarproject; - -import org.briarproject.api.blogs.BlogManager; -import org.briarproject.api.blogs.BlogSharingManager; -import org.briarproject.api.clients.MessageTracker; -import org.briarproject.api.contact.ContactManager; -import org.briarproject.api.event.EventBus; -import org.briarproject.api.identity.IdentityManager; -import org.briarproject.api.lifecycle.LifecycleManager; -import org.briarproject.api.sync.SyncSessionFactory; -import org.briarproject.blogs.BlogsModule; -import org.briarproject.clients.ClientsModule; -import org.briarproject.contact.ContactModule; -import org.briarproject.crypto.CryptoModule; -import org.briarproject.data.DataModule; -import org.briarproject.db.DatabaseModule; -import org.briarproject.event.EventModule; -import org.briarproject.forum.ForumModule; -import org.briarproject.identity.IdentityModule; -import org.briarproject.lifecycle.LifecycleModule; -import org.briarproject.messaging.MessagingModule; -import org.briarproject.properties.PropertiesModule; -import org.briarproject.sharing.SharingModule; -import org.briarproject.sync.SyncModule; -import org.briarproject.system.SystemModule; -import org.briarproject.transport.TransportModule; - -import javax.inject.Singleton; - -import dagger.Component; - -@Singleton -@Component(modules = { - TestDatabaseModule.class, - TestPluginsModule.class, - TestSeedProviderModule.class, - ClientsModule.class, - ContactModule.class, - CryptoModule.class, - DataModule.class, - DatabaseModule.class, - EventModule.class, - BlogsModule.class, - ForumModule.class, - IdentityModule.class, - LifecycleModule.class, - PropertiesModule.class, - SharingModule.class, - SyncModule.class, - SystemModule.class, - TransportModule.class, - MessagingModule.class -}) -interface BlogSharingIntegrationTestComponent { - - void inject(BlogSharingIntegrationTest testCase); - - void inject(ContactModule.EagerSingletons init); - - void inject(CryptoModule.EagerSingletons init); - - void inject(BlogsModule.EagerSingletons init); - - void inject(LifecycleModule.EagerSingletons init); - - void inject(PropertiesModule.EagerSingletons init); - - void inject(SharingModule.EagerSingletons init); - - void inject(SyncModule.EagerSingletons init); - - void inject(TransportModule.EagerSingletons init); - - LifecycleManager getLifecycleManager(); - - EventBus getEventBus(); - - IdentityManager getIdentityManager(); - - ContactManager getContactManager(); - - BlogSharingManager getBlogSharingManager(); - - BlogManager getBlogManager(); - - MessageTracker getMessageTracker(); - - SyncSessionFactory getSyncSessionFactory(); - -} diff --git a/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTest.java index 3436fe962ec9c22d37033c876c83f6ae3a1c2b23..1e0486df4cd4c3986660958518619ff63162ddf2 100644 --- a/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTest.java @@ -1,30 +1,360 @@ package org.briarproject; +import android.support.annotation.CallSuper; + +import net.jodah.concurrentunit.Waiter; + +import org.briarproject.api.blogs.BlogFactory; +import org.briarproject.api.blogs.BlogPostFactory; +import org.briarproject.api.clients.ClientHelper; +import org.briarproject.api.clients.ContactGroupFactory; import org.briarproject.api.clients.MessageTracker; -import org.briarproject.api.clients.MessageTracker.GroupCount; +import org.briarproject.api.contact.Contact; +import org.briarproject.api.contact.ContactId; +import org.briarproject.api.contact.ContactManager; +import org.briarproject.api.crypto.CryptoComponent; +import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DbException; -import org.briarproject.api.sync.GroupId; +import org.briarproject.api.event.Event; +import org.briarproject.api.event.EventListener; +import org.briarproject.api.event.MessageStateChangedEvent; +import org.briarproject.api.forum.ForumPostFactory; +import org.briarproject.api.identity.AuthorFactory; +import org.briarproject.api.identity.IdentityManager; +import org.briarproject.api.identity.LocalAuthor; +import org.briarproject.api.lifecycle.LifecycleManager; +import org.briarproject.api.nullsafety.MethodsNotNullByDefault; +import org.briarproject.api.nullsafety.ParametersNotNullByDefault; +import org.briarproject.api.privategroup.GroupMessageFactory; +import org.briarproject.api.privategroup.PrivateGroupFactory; +import org.briarproject.api.privategroup.invitation.GroupInvitationFactory; +import org.briarproject.api.sync.SyncSession; +import org.briarproject.api.sync.SyncSessionFactory; +import org.briarproject.api.system.Clock; +import org.briarproject.blogs.BlogsModule; +import org.briarproject.contact.ContactModule; +import org.briarproject.crypto.CryptoModule; +import org.briarproject.forum.ForumModule; +import org.briarproject.introduction.IntroductionGroupFactory; +import org.briarproject.introduction.IntroductionModule; +import org.briarproject.lifecycle.LifecycleModule; +import org.briarproject.privategroup.PrivateGroupModule; +import org.briarproject.properties.PropertiesModule; +import org.briarproject.sharing.SharingModule; +import org.briarproject.sync.SyncModule; +import org.briarproject.transport.TransportModule; +import org.jetbrains.annotations.Nullable; +import org.junit.After; +import org.junit.Before; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.util.concurrent.TimeoutException; +import java.util.logging.Logger; + +import javax.inject.Inject; -import static org.junit.Assert.assertEquals; +import static junit.framework.Assert.assertNotNull; +import static org.briarproject.TestPluginsModule.MAX_LATENCY; +import static org.briarproject.TestUtils.getSecretKey; +import static org.briarproject.api.sync.ValidationManager.State.DELIVERED; +import static org.briarproject.api.sync.ValidationManager.State.INVALID; +import static org.briarproject.api.sync.ValidationManager.State.PENDING; +import static org.junit.Assert.assertTrue; +@MethodsNotNullByDefault +@ParametersNotNullByDefault public abstract class BriarIntegrationTest extends BriarTestCase { - protected static void assertGroupCount(MessageTracker tracker, GroupId g, - long msgCount, long unreadCount, long latestMsg) - throws DbException { + private static final Logger LOG = + Logger.getLogger(BriarIntegrationTest.class.getName()); + + @Nullable + protected ContactId contactId1From2, contactId2From1; + protected ContactId contactId0From1, contactId0From2, contactId1From0, + contactId2From0; + protected Contact contact0From1, contact0From2, contact1From0, + contact2From0; + protected LocalAuthor author0, author1, author2; + protected ContactManager contactManager0, contactManager1, contactManager2; + protected IdentityManager identityManager0, identityManager1, + identityManager2; + protected DatabaseComponent db0, db1, db2; + protected MessageTracker messageTracker0, messageTracker1, messageTracker2; + + private LifecycleManager lifecycleManager0, lifecycleManager1, + lifecycleManager2; + private SyncSessionFactory sync0, sync1, sync2; + + @Inject + protected Clock clock; + @Inject + protected CryptoComponent crypto; + @Inject + protected ClientHelper clientHelper; + @Inject + protected AuthorFactory authorFactory; + @Inject + protected IntroductionGroupFactory introductionGroupFactory; + @Inject + ContactGroupFactory contactGroupFactory; + @Inject + PrivateGroupFactory privateGroupFactory; + @Inject + GroupMessageFactory groupMessageFactory; + @Inject + GroupInvitationFactory groupInvitationFactory; + @Inject + BlogFactory blogFactory; + @Inject + BlogPostFactory blogPostFactory; + @Inject + ForumPostFactory forumPostFactory; + + // objects accessed from background threads need to be volatile + private volatile Waiter validationWaiter; + private volatile Waiter deliveryWaiter; + + protected final static int TIMEOUT = 15000; + protected BriarIntegrationTestComponent c0, c1, c2; + + private final File testDir = TestUtils.getTestDirectory(); + private final String AUTHOR0 = "Author 0"; + private final String AUTHOR1 = "Author 1"; + private final String AUTHOR2 = "Author 2"; + + @Before + @CallSuper + public void setUp() throws Exception { + BriarIntegrationTestComponent component = + DaggerBriarIntegrationTestComponent.builder().build(); + component.inject(this); + + assertTrue(testDir.mkdirs()); + File t0Dir = new File(testDir, AUTHOR0); + c0 = DaggerBriarIntegrationTestComponent.builder() + .testDatabaseModule(new TestDatabaseModule(t0Dir)).build(); + injectEagerSingletons(c0); + File t1Dir = new File(testDir, AUTHOR1); + c1 = DaggerBriarIntegrationTestComponent.builder() + .testDatabaseModule(new TestDatabaseModule(t1Dir)).build(); + injectEagerSingletons(c1); + File t2Dir = new File(testDir, AUTHOR2); + c2 = DaggerBriarIntegrationTestComponent.builder() + .testDatabaseModule(new TestDatabaseModule(t2Dir)).build(); + injectEagerSingletons(c2); + + identityManager0 = c0.getIdentityManager(); + identityManager1 = c1.getIdentityManager(); + identityManager2 = c2.getIdentityManager(); + contactManager0 = c0.getContactManager(); + contactManager1 = c1.getContactManager(); + contactManager2 = c2.getContactManager(); + messageTracker0 = c0.getMessageTracker(); + messageTracker1 = c1.getMessageTracker(); + messageTracker2 = c2.getMessageTracker(); + db0 = c0.getDatabaseComponent(); + db1 = c1.getDatabaseComponent(); + db2 = c2.getDatabaseComponent(); + sync0 = c0.getSyncSessionFactory(); + sync1 = c1.getSyncSessionFactory(); + sync2 = c2.getSyncSessionFactory(); - GroupCount groupCount = tracker.getGroupCount(g); - assertEquals(msgCount, groupCount.getMsgCount()); - assertEquals(unreadCount, groupCount.getUnreadCount()); - assertEquals(latestMsg, groupCount.getLatestMsgTime()); + // initialize waiters fresh for each test + validationWaiter = new Waiter(); + deliveryWaiter = new Waiter(); + + startLifecycles(); + + getDefaultIdentities(); + addDefaultContacts(); + listenToEvents(); + } + + private void injectEagerSingletons( + BriarIntegrationTestComponent component) { + component.inject(new LifecycleModule.EagerSingletons()); + component.inject(new BlogsModule.EagerSingletons()); + component.inject(new CryptoModule.EagerSingletons()); + component.inject(new ContactModule.EagerSingletons()); + component.inject(new ForumModule.EagerSingletons()); + component.inject(new IntroductionModule.EagerSingletons()); + component.inject(new PropertiesModule.EagerSingletons()); + component.inject(new PrivateGroupModule.EagerSingletons()); + component.inject(new SyncModule.EagerSingletons()); + component.inject(new SharingModule.EagerSingletons()); + component.inject(new TransportModule.EagerSingletons()); + } + + private void startLifecycles() throws InterruptedException { + // Start the lifecycle manager and wait for it to finish + lifecycleManager0 = c0.getLifecycleManager(); + lifecycleManager1 = c1.getLifecycleManager(); + lifecycleManager2 = c2.getLifecycleManager(); + lifecycleManager0.startServices(AUTHOR0); + lifecycleManager1.startServices(AUTHOR1); + lifecycleManager2.startServices(AUTHOR2); + lifecycleManager0.waitForStartup(); + lifecycleManager1.waitForStartup(); + lifecycleManager2.waitForStartup(); } - protected static void assertGroupCount(MessageTracker tracker, GroupId g, - long msgCount, long unreadCount) throws DbException { + private void listenToEvents() { + Listener listener0 = new Listener(); + c0.getEventBus().addListener(listener0); + Listener listener1 = new Listener(); + c1.getEventBus().addListener(listener1); + Listener listener2 = new Listener(); + c2.getEventBus().addListener(listener2); + } + + private class Listener implements EventListener { + @Override + public void eventOccurred(Event e) { + if (e instanceof MessageStateChangedEvent) { + MessageStateChangedEvent event = (MessageStateChangedEvent) e; + if (!event.isLocal()) { + if (event.getState() == DELIVERED) { + LOG.info("Delivered new message"); + deliveryWaiter.resume(); + } else if (event.getState() == INVALID || + event.getState() == PENDING) { + LOG.info("Validated new " + event.getState().name() + + " message"); + validationWaiter.resume(); + } + } + } + } + } - GroupCount c1 = tracker.getGroupCount(g); - assertEquals(msgCount, c1.getMsgCount()); - assertEquals(unreadCount, c1.getUnreadCount()); + private void getDefaultIdentities() throws DbException { + author0 = identityManager0.getLocalAuthor(); + author1 = identityManager1.getLocalAuthor(); + author2 = identityManager2.getLocalAuthor(); } + protected void addDefaultContacts() throws DbException { + contactId1From0 = contactManager0 + .addContact(author1, author0.getId(), getSecretKey(), + clock.currentTimeMillis(), true, true, true); + contact1From0 = contactManager0.getContact(contactId1From0); + contactId0From1 = contactManager1 + .addContact(author0, author1.getId(), getSecretKey(), + clock.currentTimeMillis(), true, true, true); + contact0From1 = contactManager1.getContact(contactId0From1); + contactId2From0 = contactManager0 + .addContact(author2, author0.getId(), getSecretKey(), + clock.currentTimeMillis(), true, true, true); + contact2From0 = contactManager0.getContact(contactId2From0); + contactId0From2 = contactManager2 + .addContact(author0, author2.getId(), getSecretKey(), + clock.currentTimeMillis(), true, true, true); + contact0From2 = contactManager2.getContact(contactId0From2); + } + + protected void addContacts1And2() throws DbException { + contactId2From1 = contactManager1 + .addContact(author2, author1.getId(), getSecretKey(), + clock.currentTimeMillis(), true, true, true); + contactId1From2 = contactManager2 + .addContact(author1, author2.getId(), getSecretKey(), + clock.currentTimeMillis(), true, true, true); + } + + @After + public void tearDown() throws Exception { + stopLifecycles(); + TestUtils.deleteTestDirectory(testDir); + } + + private void stopLifecycles() throws InterruptedException { + // Clean up + lifecycleManager0.stopServices(); + lifecycleManager1.stopServices(); + lifecycleManager2.stopServices(); + lifecycleManager0.waitForShutdown(); + lifecycleManager1.waitForShutdown(); + lifecycleManager2.waitForShutdown(); + } + + protected void sync0To1(int num, boolean valid) + throws IOException, TimeoutException { + syncMessage(sync0, contactId0From1, sync1, contactId1From0, num, valid); + } + + protected void sync0To2(int num, boolean valid) + throws IOException, TimeoutException { + syncMessage(sync0, contactId0From2, sync2, contactId2From0, num, valid); + } + + protected void sync1To0(int num, boolean valid) + throws IOException, TimeoutException { + syncMessage(sync1, contactId1From0, sync0, contactId0From1, num, valid); + } + + protected void sync2To0(int num, boolean valid) + throws IOException, TimeoutException { + syncMessage(sync2, contactId2From0, sync0, contactId0From2, num, valid); + } + + protected void sync2To1(int num, boolean valid) + throws IOException, TimeoutException { + assertNotNull(contactId2From1); + assertNotNull(contactId1From2); + syncMessage(sync2, contactId2From1, sync1, contactId1From2, num, valid); + } + + protected void sync1To2(int num, boolean valid) + throws IOException, TimeoutException { + assertNotNull(contactId2From1); + assertNotNull(contactId1From2); + syncMessage(sync1, contactId1From2, sync2, contactId2From1, num, valid); + } + + private void syncMessage(SyncSessionFactory fromSync, ContactId fromId, + SyncSessionFactory toSync, ContactId toId, int num, boolean valid) + throws IOException, TimeoutException { + + // Debug output + String from = "0"; + if (fromSync == sync1) from = "1"; + else if (fromSync == sync2) from = "2"; + String to = "0"; + if (toSync == sync1) to = "1"; + else if (toSync == sync2) to = "2"; + LOG.info("TEST: Sending message from " + from + " to " + to); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + // Create an outgoing sync session + SyncSession sessionFrom = + fromSync.createSimplexOutgoingSession(toId, MAX_LATENCY, out); + // Write whatever needs to be written + sessionFrom.run(); + out.close(); + + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + // Create an incoming sync session + SyncSession sessionTo = toSync.createIncomingSession(fromId, in); + // Read whatever needs to be read + sessionTo.run(); + in.close(); + + if (valid) { + deliveryWaiter.await(TIMEOUT, num); + } else { + validationWaiter.await(TIMEOUT, num); + } + } + + protected void removeAllContacts() throws DbException { + contactManager0.removeContact(contactId1From0); + contactManager0.removeContact(contactId2From0); + contactManager1.removeContact(contactId0From1); + contactManager1.removeContact(contactId2From1); + contactManager2.removeContact(contactId0From2); + contactManager2.removeContact(contactId1From2); + } } diff --git a/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTestComponent.java b/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTestComponent.java similarity index 67% rename from briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTestComponent.java rename to briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTestComponent.java index 88b058807ce19031ffa8f311ffb8c42c2cd55708..835c345bd758afd9684e936fc421b6fb29b815b4 100644 --- a/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTestComponent.java +++ b/briar-android-tests/src/test/java/org/briarproject/BriarIntegrationTestComponent.java @@ -1,15 +1,20 @@ package org.briarproject; +import org.briarproject.api.blogs.BlogManager; +import org.briarproject.api.blogs.BlogSharingManager; import org.briarproject.api.clients.ClientHelper; import org.briarproject.api.clients.MessageQueueManager; -import org.briarproject.api.clients.ContactGroupFactory; +import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.contact.ContactManager; import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.event.EventBus; import org.briarproject.api.forum.ForumManager; import org.briarproject.api.forum.ForumSharingManager; import org.briarproject.api.identity.IdentityManager; +import org.briarproject.api.introduction.IntroductionManager; import org.briarproject.api.lifecycle.LifecycleManager; +import org.briarproject.api.privategroup.PrivateGroupManager; +import org.briarproject.api.properties.TransportPropertyManager; import org.briarproject.api.sync.SyncSessionFactory; import org.briarproject.blogs.BlogsModule; import org.briarproject.clients.ClientsModule; @@ -20,8 +25,12 @@ import org.briarproject.db.DatabaseModule; import org.briarproject.event.EventModule; import org.briarproject.forum.ForumModule; import org.briarproject.identity.IdentityModule; +import org.briarproject.introduction.IntroductionModule; +import org.briarproject.introduction.MessageSender; import org.briarproject.lifecycle.LifecycleModule; import org.briarproject.messaging.MessagingModule; +import org.briarproject.privategroup.PrivateGroupModule; +import org.briarproject.privategroup.invitation.GroupInvitationModule; import org.briarproject.properties.PropertiesModule; import org.briarproject.sharing.SharingModule; import org.briarproject.sync.SyncModule; @@ -40,23 +49,28 @@ import dagger.Component; ClientsModule.class, ContactModule.class, CryptoModule.class, + BlogsModule.class, DataModule.class, DatabaseModule.class, EventModule.class, ForumModule.class, - BlogsModule.class, + GroupInvitationModule.class, + MessagingModule.class, IdentityModule.class, + IntroductionModule.class, LifecycleModule.class, + PrivateGroupModule.class, PropertiesModule.class, SharingModule.class, SyncModule.class, SystemModule.class, - TransportModule.class, - MessagingModule.class + TransportModule.class }) -interface ForumSharingIntegrationTestComponent { +public interface BriarIntegrationTestComponent { + + void inject(BriarIntegrationTest init); - void inject(ForumSharingIntegrationTest testCase); + void inject(BlogsModule.EagerSingletons init); void inject(ContactModule.EagerSingletons init); @@ -64,8 +78,12 @@ interface ForumSharingIntegrationTestComponent { void inject(ForumModule.EagerSingletons init); + void inject(IntroductionModule.EagerSingletons init); + void inject(LifecycleModule.EagerSingletons init); + void inject(PrivateGroupModule.EagerSingletons init); + void inject(PropertiesModule.EagerSingletons init); void inject(SharingModule.EagerSingletons init); @@ -80,22 +98,32 @@ interface ForumSharingIntegrationTestComponent { IdentityManager getIdentityManager(); + ClientHelper getClientHelper(); + ContactManager getContactManager(); + SyncSessionFactory getSyncSessionFactory(); + + DatabaseComponent getDatabaseComponent(); + + BlogManager getBlogManager(); + + BlogSharingManager getBlogSharingManager(); + ForumSharingManager getForumSharingManager(); ForumManager getForumManager(); - SyncSessionFactory getSyncSessionFactory(); + IntroductionManager getIntroductionManager(); - /* the following methods are only needed to manually construct messages */ + MessageTracker getMessageTracker(); - DatabaseComponent getDatabaseComponent(); + MessageSender getMessageSender(); - ContactGroupFactory getContactGroupFactory(); + MessageQueueManager getMessageQueueManager(); - ClientHelper getClientHelper(); + PrivateGroupManager getPrivateGroupManager(); - MessageQueueManager getMessageQueueManager(); + TransportPropertyManager getTransportPropertyManager(); } diff --git a/briar-android-tests/src/test/java/org/briarproject/ForumManagerTest.java b/briar-android-tests/src/test/java/org/briarproject/ForumManagerTest.java index e574d224ae38278d9edd50ee43d0fbf4c50d4658..3d5c827d0fe946ce23fd546b9b91f28a7a105b88 100644 --- a/briar-android-tests/src/test/java/org/briarproject/ForumManagerTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/ForumManagerTest.java @@ -2,135 +2,49 @@ package org.briarproject; import junit.framework.Assert; -import net.jodah.concurrentunit.Waiter; - -import org.briarproject.api.clients.MessageTracker; -import org.briarproject.api.contact.Contact; -import org.briarproject.api.contact.ContactId; -import org.briarproject.api.contact.ContactManager; -import org.briarproject.api.crypto.CryptoComponent; -import org.briarproject.api.crypto.SecretKey; -import org.briarproject.api.db.DbException; -import org.briarproject.api.event.Event; -import org.briarproject.api.event.EventListener; -import org.briarproject.api.event.MessageStateChangedEvent; import org.briarproject.api.forum.Forum; import org.briarproject.api.forum.ForumManager; import org.briarproject.api.forum.ForumPost; -import org.briarproject.api.forum.ForumPostFactory; import org.briarproject.api.forum.ForumPostHeader; import org.briarproject.api.forum.ForumSharingManager; -import org.briarproject.api.identity.AuthorFactory; -import org.briarproject.api.identity.IdentityManager; -import org.briarproject.api.identity.LocalAuthor; -import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.sync.GroupId; -import org.briarproject.api.sync.SyncSession; -import org.briarproject.api.sync.SyncSessionFactory; -import org.briarproject.api.system.Clock; -import org.briarproject.contact.ContactModule; -import org.briarproject.crypto.CryptoModule; -import org.briarproject.forum.ForumModule; -import org.briarproject.lifecycle.LifecycleModule; -import org.briarproject.properties.PropertiesModule; -import org.briarproject.sharing.SharingModule; -import org.briarproject.sync.SyncModule; -import org.briarproject.transport.TransportModule; import org.jetbrains.annotations.Nullable; -import org.junit.After; import org.junit.Before; import org.junit.Test; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; import java.util.Collection; -import java.util.concurrent.TimeoutException; -import java.util.logging.Logger; - -import javax.inject.Inject; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNull; import static junit.framework.TestCase.assertFalse; -import static org.briarproject.TestPluginsModule.MAX_LATENCY; -import static org.briarproject.api.sync.ValidationManager.State.DELIVERED; -import static org.briarproject.api.sync.ValidationManager.State.INVALID; -import static org.briarproject.api.sync.ValidationManager.State.PENDING; +import static org.briarproject.TestUtils.assertGroupCount; import static org.junit.Assert.assertTrue; public class ForumManagerTest extends BriarIntegrationTest { - private LifecycleManager lifecycleManager0, lifecycleManager1; - private SyncSessionFactory sync0, sync1; private ForumManager forumManager0, forumManager1; - private ContactManager contactManager0, contactManager1; - private MessageTracker messageTracker0, messageTracker1; - private ContactId contactId0,contactId1; - private IdentityManager identityManager0, identityManager1; - private LocalAuthor author0, author1; + private ForumSharingManager forumSharingManager0, forumSharingManager1; private Forum forum0; - - @Inject - Clock clock; - @Inject - AuthorFactory authorFactory; - @Inject - CryptoComponent crypto; - @Inject - ForumPostFactory forumPostFactory; - - // objects accessed from background threads need to be volatile - private volatile ForumSharingManager forumSharingManager0; - private volatile ForumSharingManager forumSharingManager1; - private volatile Waiter validationWaiter; - private volatile Waiter deliveryWaiter; - - private final File testDir = TestUtils.getTestDirectory(); - private final SecretKey master = TestUtils.getSecretKey(); - private final int TIMEOUT = 15000; - private final String SHARER = "Sharer"; - private final String INVITEE = "Invitee"; - - private static final Logger LOG = - Logger.getLogger(ForumSharingIntegrationTest.class.getName()); - - private ForumManagerTestComponent t0, t1; + private GroupId groupId0; @Before + @Override public void setUp() throws Exception { - ForumManagerTestComponent component = - DaggerForumManagerTestComponent.builder().build(); - component.inject(this); - injectEagerSingletons(component); + super.setUp(); - assertTrue(testDir.mkdirs()); - File t0Dir = new File(testDir, SHARER); - t0 = DaggerForumManagerTestComponent.builder() - .testDatabaseModule(new TestDatabaseModule(t0Dir)).build(); - injectEagerSingletons(t0); - File t1Dir = new File(testDir, INVITEE); - t1 = DaggerForumManagerTestComponent.builder() - .testDatabaseModule(new TestDatabaseModule(t1Dir)).build(); - injectEagerSingletons(t1); + forumManager0 = c0.getForumManager(); + forumManager1 = c1.getForumManager(); + forumSharingManager0 = c0.getForumSharingManager(); + forumSharingManager1 = c1.getForumSharingManager(); - identityManager0 = t0.getIdentityManager(); - identityManager1 = t1.getIdentityManager(); - contactManager0 = t0.getContactManager(); - contactManager1 = t1.getContactManager(); - messageTracker0 = t0.getMessageTracker(); - messageTracker1 = t1.getMessageTracker(); - forumManager0 = t0.getForumManager(); - forumManager1 = t1.getForumManager(); - forumSharingManager0 = t0.getForumSharingManager(); - forumSharingManager1 = t1.getForumSharingManager(); - sync0 = t0.getSyncSessionFactory(); - sync1 = t1.getSyncSessionFactory(); - // initialize waiters fresh for each test - validationWaiter = new Waiter(); - deliveryWaiter = new Waiter(); + forum0 = forumManager0.addForum("Test Forum"); + groupId0 = forum0.getId(); + // share forum + forumSharingManager0.sendInvitation(groupId0, contactId1From0, null); + sync0To1(1, true); + forumSharingManager1.respondToInvitation(forum0, contact0From1, true); + sync1To0(1, true); } private ForumPost createForumPost(GroupId groupId, @@ -142,36 +56,33 @@ public class ForumManagerTest extends BriarIntegrationTest { @Test public void testForumPost() throws Exception { - startLifecycles(); - getDefaultIdentities(); - Forum forum = forumManager0.addForum("TestForum"); assertEquals(1, forumManager0.getForums().size()); final long ms1 = clock.currentTimeMillis() - 1000L; final String body1 = "some forum text"; final long ms2 = clock.currentTimeMillis(); final String body2 = "some other forum text"; ForumPost post1 = - createForumPost(forum.getGroup().getId(), null, body1, ms1); + createForumPost(forum0.getGroup().getId(), null, body1, ms1); assertEquals(ms1, post1.getMessage().getTimestamp()); ForumPost post2 = - createForumPost(forum.getGroup().getId(), post1, body2, ms2); + createForumPost(forum0.getGroup().getId(), post1, body2, ms2); assertEquals(ms2, post2.getMessage().getTimestamp()); forumManager0.addLocalPost(post1); - forumManager0.setReadFlag(forum.getGroup().getId(), + forumManager0.setReadFlag(forum0.getGroup().getId(), post1.getMessage().getId(), true); - assertGroupCount(messageTracker0, forum.getGroup().getId(), 1, 0, + assertGroupCount(messageTracker0, forum0.getGroup().getId(), 1, 0, post1.getMessage().getTimestamp()); forumManager0.addLocalPost(post2); - forumManager0.setReadFlag(forum.getGroup().getId(), + forumManager0.setReadFlag(forum0.getGroup().getId(), post2.getMessage().getId(), false); - assertGroupCount(messageTracker0, forum.getGroup().getId(), 2, 1, + assertGroupCount(messageTracker0, forum0.getGroup().getId(), 2, 1, post2.getMessage().getTimestamp()); - forumManager0.setReadFlag(forum.getGroup().getId(), + forumManager0.setReadFlag(forum0.getGroup().getId(), post2.getMessage().getId(), false); - assertGroupCount(messageTracker0, forum.getGroup().getId(), 2, 1, + assertGroupCount(messageTracker0, forum0.getGroup().getId(), 2, 1, post2.getMessage().getTimestamp()); Collection<ForumPostHeader> headers = - forumManager0.getPostHeaders(forum.getGroup().getId()); + forumManager0.getPostHeaders(forum0.getGroup().getId()); assertEquals(2, headers.size()); for (ForumPostHeader h : headers) { final String hBody = forumManager0.getPostBody(h.getId()); @@ -184,146 +95,94 @@ public class ForumManagerTest extends BriarIntegrationTest { assertEquals(body1, hBody); assertNull(h.getParentId()); assertTrue(h.isRead()); - } - else { + } else { assertEquals(h.getTimestamp(), ms2); assertEquals(body2, hBody); assertEquals(h.getParentId(), post2.getParent()); assertFalse(h.isRead()); } } - forumManager0.removeForum(forum); + forumManager0.removeForum(forum0); assertEquals(0, forumManager0.getForums().size()); - stopLifecycles(); } @Test public void testForumPostDelivery() throws Exception { - startLifecycles(); - defaultInit(); - - // share forum - GroupId g = forum0.getId(); - forumSharingManager0.sendInvitation(g, contactId1, null); - sync0To1(); - deliveryWaiter.await(TIMEOUT, 1); - Contact c0 = contactManager1.getContact(contactId0); - forumSharingManager1.respondToInvitation(forum0, c0, true); - sync1To0(); - deliveryWaiter.await(TIMEOUT, 1); - // add one forum post long time = clock.currentTimeMillis(); - ForumPost post1 = createForumPost(g, null, "a", time); + ForumPost post1 = createForumPost(groupId0, null, "a", time); forumManager0.addLocalPost(post1); - assertEquals(1, forumManager0.getPostHeaders(g).size()); - assertEquals(0, forumManager1.getPostHeaders(g).size()); - assertGroupCount(messageTracker0, g, 1, 0, time); - assertGroupCount(messageTracker1, g, 0, 0, 0); + assertEquals(1, forumManager0.getPostHeaders(groupId0).size()); + assertEquals(0, forumManager1.getPostHeaders(groupId0).size()); + assertGroupCount(messageTracker0, groupId0, 1, 0, time); + assertGroupCount(messageTracker1, groupId0, 0, 0, 0); // send post to 1 - sync0To1(); - deliveryWaiter.await(TIMEOUT, 1); - assertEquals(1, forumManager1.getPostHeaders(g).size()); - assertGroupCount(messageTracker1, g, 1, 1, time); + sync0To1(1, true); + assertEquals(1, forumManager1.getPostHeaders(groupId0).size()); + assertGroupCount(messageTracker1, groupId0, 1, 1, time); // add another forum post long time2 = clock.currentTimeMillis(); - ForumPost post2 = createForumPost(g, null, "b", time2); + ForumPost post2 = createForumPost(groupId0, null, "b", time2); forumManager1.addLocalPost(post2); - assertEquals(1, forumManager0.getPostHeaders(g).size()); - assertEquals(2, forumManager1.getPostHeaders(g).size()); - assertGroupCount(messageTracker0, g, 1, 0, time); - assertGroupCount(messageTracker1, g, 2, 1, time2); + assertEquals(1, forumManager0.getPostHeaders(groupId0).size()); + assertEquals(2, forumManager1.getPostHeaders(groupId0).size()); + assertGroupCount(messageTracker0, groupId0, 1, 0, time); + assertGroupCount(messageTracker1, groupId0, 2, 1, time2); // send post to 0 - sync1To0(); - deliveryWaiter.await(TIMEOUT, 1); - assertEquals(2, forumManager1.getPostHeaders(g).size()); - assertGroupCount(messageTracker0, g, 2, 1, time2); - - stopLifecycles(); + sync1To0(1, true); + assertEquals(2, forumManager1.getPostHeaders(groupId0).size()); + assertGroupCount(messageTracker0, groupId0, 2, 1, time2); } @Test public void testForumPostDeliveredAfterParent() throws Exception { - startLifecycles(); - defaultInit(); - - // share forum - GroupId g = forum0.getId(); - forumSharingManager0.sendInvitation(g, contactId1, null); - sync0To1(); - deliveryWaiter.await(TIMEOUT, 1); - Contact c0 = contactManager1.getContact(contactId0); - forumSharingManager1.respondToInvitation(forum0, c0, true); - sync1To0(); - deliveryWaiter.await(TIMEOUT, 1); - // add one forum post without the parent long time = clock.currentTimeMillis(); - ForumPost post1 = createForumPost(g, null, "a", time); - ForumPost post2 = createForumPost(g, post1, "a", time); + ForumPost post1 = createForumPost(groupId0, null, "a", time); + ForumPost post2 = createForumPost(groupId0, post1, "a", time); forumManager0.addLocalPost(post2); - assertEquals(1, forumManager0.getPostHeaders(g).size()); - assertEquals(0, forumManager1.getPostHeaders(g).size()); + assertEquals(1, forumManager0.getPostHeaders(groupId0).size()); + assertEquals(0, forumManager1.getPostHeaders(groupId0).size()); // send post to 1 without waiting for message delivery - sync0To1(); - validationWaiter.await(TIMEOUT, 1); - assertEquals(0, forumManager1.getPostHeaders(g).size()); + sync0To1(1, false); + assertEquals(0, forumManager1.getPostHeaders(groupId0).size()); // now add the parent post as well forumManager0.addLocalPost(post1); - assertEquals(2, forumManager0.getPostHeaders(g).size()); - assertEquals(0, forumManager1.getPostHeaders(g).size()); + assertEquals(2, forumManager0.getPostHeaders(groupId0).size()); + assertEquals(0, forumManager1.getPostHeaders(groupId0).size()); // and send it over to 1 and wait for a second message to be delivered - sync0To1(); - deliveryWaiter.await(TIMEOUT, 2); - assertEquals(2, forumManager1.getPostHeaders(g).size()); - - stopLifecycles(); + sync0To1(2, true); + assertEquals(2, forumManager1.getPostHeaders(groupId0).size()); } @Test public void testForumPostWithParentInOtherGroup() throws Exception { - startLifecycles(); - defaultInit(); - - // share forum - GroupId g = forum0.getId(); - forumSharingManager0.sendInvitation(g, contactId1, null); - sync0To1(); - deliveryWaiter.await(TIMEOUT, 1); - Contact c0 = contactManager1.getContact(contactId0); - forumSharingManager1.respondToInvitation(forum0, c0, true); - sync1To0(); - deliveryWaiter.await(TIMEOUT, 1); - // share a second forum Forum forum1 = forumManager0.addForum("Test Forum1"); GroupId g1 = forum1.getId(); - forumSharingManager0.sendInvitation(g1, contactId1, null); - sync0To1(); - deliveryWaiter.await(TIMEOUT, 1); - forumSharingManager1.respondToInvitation(forum1, c0, true); - sync1To0(); - deliveryWaiter.await(TIMEOUT, 1); + forumSharingManager0.sendInvitation(g1, contactId1From0, null); + sync0To1(1, true); + forumSharingManager1.respondToInvitation(forum1, contact0From1, true); + sync1To0(1, true); // add one forum post with a parent in another forum long time = clock.currentTimeMillis(); ForumPost post1 = createForumPost(g1, null, "a", time); - ForumPost post = createForumPost(g, post1, "b", time); + ForumPost post = createForumPost(groupId0, post1, "b", time); forumManager0.addLocalPost(post); - assertEquals(1, forumManager0.getPostHeaders(g).size()); - assertEquals(0, forumManager1.getPostHeaders(g).size()); + assertEquals(1, forumManager0.getPostHeaders(groupId0).size()); + assertEquals(0, forumManager1.getPostHeaders(groupId0).size()); // send the child post to 1 - sync0To1(); - validationWaiter.await(TIMEOUT, 1); - assertEquals(1, forumManager0.getPostHeaders(g).size()); - assertEquals(0, forumManager1.getPostHeaders(g).size()); + sync0To1(1, false); + assertEquals(1, forumManager0.getPostHeaders(groupId0).size()); + assertEquals(0, forumManager1.getPostHeaders(groupId0).size()); // now also add the parent post which is in another group forumManager0.addLocalPost(post1); @@ -331,132 +190,12 @@ public class ForumManagerTest extends BriarIntegrationTest { assertEquals(0, forumManager1.getPostHeaders(g1).size()); // send posts to 1 - sync0To1(); - deliveryWaiter.await(TIMEOUT, 1); - assertEquals(1, forumManager0.getPostHeaders(g).size()); + sync0To1(1, true); + assertEquals(1, forumManager0.getPostHeaders(groupId0).size()); assertEquals(1, forumManager0.getPostHeaders(g1).size()); // the next line is critical, makes sure post doesn't show up - assertEquals(0, forumManager1.getPostHeaders(g).size()); + assertEquals(0, forumManager1.getPostHeaders(groupId0).size()); assertEquals(1, forumManager1.getPostHeaders(g1).size()); - - stopLifecycles(); - } - - @After - public void tearDown() throws Exception { - TestUtils.deleteTestDirectory(testDir); - } - - private class Listener implements EventListener { - @Override - public void eventOccurred(Event e) { - if (e instanceof MessageStateChangedEvent) { - MessageStateChangedEvent event = (MessageStateChangedEvent) e; - if (!event.isLocal()) { - if (event.getState() == DELIVERED) { - deliveryWaiter.resume(); - } else if (event.getState() == INVALID || - event.getState() == PENDING) { - validationWaiter.resume(); - } - } - } - } - } - - private void defaultInit() throws DbException { - getDefaultIdentities(); - addDefaultContacts(); - addForum(); - listenToEvents(); - } - - private void getDefaultIdentities() throws DbException { - author0 = identityManager0.getLocalAuthor(); - author1 = identityManager1.getLocalAuthor(); - } - - private void addDefaultContacts() throws DbException { - // sharer adds invitee as contact - contactId1 = contactManager0.addContact(author1, - author0.getId(), master, clock.currentTimeMillis(), true, - true, true - ); - // invitee adds sharer back - contactId0 = contactManager1.addContact(author0, - author1.getId(), master, clock.currentTimeMillis(), true, - true, true - ); - } - - private void addForum() throws DbException { - forum0 = forumManager0.addForum("Test Forum"); - } - - private void listenToEvents() { - Listener listener0 = new Listener(); - t0.getEventBus().addListener(listener0); - Listener listener1 = new Listener(); - t1.getEventBus().addListener(listener1); - } - - private void sync0To1() throws IOException, TimeoutException { - deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1"); - } - - private void sync1To0() throws IOException, TimeoutException { - deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0"); - } - - private void deliverMessage(SyncSessionFactory fromSync, ContactId fromId, - SyncSessionFactory toSync, ContactId toId, String debug) - throws IOException, TimeoutException { - - if (debug != null) LOG.info("TEST: Sending message from " + debug); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - // Create an outgoing sync session - SyncSession sessionFrom = - fromSync.createSimplexOutgoingSession(toId, MAX_LATENCY, out); - // Write whatever needs to be written - sessionFrom.run(); - out.close(); - - ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); - // Create an incoming sync session - SyncSession sessionTo = toSync.createIncomingSession(fromId, in); - // Read whatever needs to be read - sessionTo.run(); - in.close(); - } - - private void startLifecycles() throws InterruptedException { - // Start the lifecycle manager and wait for it to finish - lifecycleManager0 = t0.getLifecycleManager(); - lifecycleManager1 = t1.getLifecycleManager(); - lifecycleManager0.startServices(SHARER); - lifecycleManager1.startServices(INVITEE); - lifecycleManager0.waitForStartup(); - lifecycleManager1.waitForStartup(); - } - - private void stopLifecycles() throws InterruptedException { - // Clean up - lifecycleManager0.stopServices(); - lifecycleManager1.stopServices(); - lifecycleManager0.waitForShutdown(); - lifecycleManager1.waitForShutdown(); - } - - private void injectEagerSingletons(ForumManagerTestComponent component) { - component.inject(new LifecycleModule.EagerSingletons()); - component.inject(new ForumModule.EagerSingletons()); - component.inject(new CryptoModule.EagerSingletons()); - component.inject(new ContactModule.EagerSingletons()); - component.inject(new TransportModule.EagerSingletons()); - component.inject(new SharingModule.EagerSingletons()); - component.inject(new SyncModule.EagerSingletons()); - component.inject(new PropertiesModule.EagerSingletons()); } } diff --git a/briar-android-tests/src/test/java/org/briarproject/ForumManagerTestComponent.java b/briar-android-tests/src/test/java/org/briarproject/ForumManagerTestComponent.java deleted file mode 100644 index 24278e4af5e878c5c16e9ff55730fd0fa52044cd..0000000000000000000000000000000000000000 --- a/briar-android-tests/src/test/java/org/briarproject/ForumManagerTestComponent.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.briarproject; - -import org.briarproject.api.clients.MessageTracker; -import org.briarproject.api.contact.ContactManager; -import org.briarproject.api.event.EventBus; -import org.briarproject.api.forum.ForumManager; -import org.briarproject.api.forum.ForumSharingManager; -import org.briarproject.api.identity.IdentityManager; -import org.briarproject.api.lifecycle.LifecycleManager; -import org.briarproject.api.sync.SyncSessionFactory; -import org.briarproject.blogs.BlogsModule; -import org.briarproject.clients.ClientsModule; -import org.briarproject.contact.ContactModule; -import org.briarproject.crypto.CryptoModule; -import org.briarproject.data.DataModule; -import org.briarproject.db.DatabaseModule; -import org.briarproject.event.EventModule; -import org.briarproject.forum.ForumModule; -import org.briarproject.identity.IdentityModule; -import org.briarproject.lifecycle.LifecycleModule; -import org.briarproject.messaging.MessagingModule; -import org.briarproject.properties.PropertiesModule; -import org.briarproject.sharing.SharingModule; -import org.briarproject.sync.SyncModule; -import org.briarproject.system.SystemModule; -import org.briarproject.transport.TransportModule; - -import javax.inject.Singleton; - -import dagger.Component; - -@Singleton -@Component(modules = { - TestDatabaseModule.class, - TestPluginsModule.class, - TestSeedProviderModule.class, - ClientsModule.class, - ContactModule.class, - CryptoModule.class, - DataModule.class, - DatabaseModule.class, - EventModule.class, - ForumModule.class, - BlogsModule.class, - IdentityModule.class, - LifecycleModule.class, - PropertiesModule.class, - SharingModule.class, - SyncModule.class, - SystemModule.class, - TransportModule.class, - MessagingModule.class -}) -interface ForumManagerTestComponent { - - void inject(ForumManagerTest testCase); - - void inject(ContactModule.EagerSingletons init); - - void inject(CryptoModule.EagerSingletons init); - - void inject(ForumModule.EagerSingletons init); - - void inject(LifecycleModule.EagerSingletons init); - - void inject(PropertiesModule.EagerSingletons init); - - void inject(SharingModule.EagerSingletons init); - - void inject(SyncModule.EagerSingletons init); - - void inject(TransportModule.EagerSingletons init); - - LifecycleManager getLifecycleManager(); - - EventBus getEventBus(); - - IdentityManager getIdentityManager(); - - ContactManager getContactManager(); - - MessageTracker getMessageTracker(); - - ForumSharingManager getForumSharingManager(); - - ForumManager getForumManager(); - - SyncSessionFactory getSyncSessionFactory(); - -} diff --git a/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java index 896e54e694c7cde207b202a707dafdcce322a467..249354bd2116147efba70b1a05a6be6af6981935 100644 --- a/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/ForumSharingIntegrationTest.java @@ -3,16 +3,10 @@ package org.briarproject; import net.jodah.concurrentunit.Waiter; import org.briarproject.api.Bytes; -import org.briarproject.api.clients.ContactGroupFactory; import org.briarproject.api.clients.MessageQueueManager; import org.briarproject.api.clients.SessionId; import org.briarproject.api.contact.Contact; -import org.briarproject.api.contact.ContactId; -import org.briarproject.api.contact.ContactManager; -import org.briarproject.api.crypto.CryptoComponent; -import org.briarproject.api.crypto.SecretKey; import org.briarproject.api.data.BdfList; -import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DbException; import org.briarproject.api.db.Metadata; import org.briarproject.api.db.Transaction; @@ -20,894 +14,742 @@ import org.briarproject.api.event.Event; import org.briarproject.api.event.EventListener; import org.briarproject.api.event.ForumInvitationReceivedEvent; import org.briarproject.api.event.ForumInvitationResponseReceivedEvent; -import org.briarproject.api.event.MessageStateChangedEvent; import org.briarproject.api.forum.Forum; import org.briarproject.api.forum.ForumInvitationRequest; import org.briarproject.api.forum.ForumInvitationResponse; import org.briarproject.api.forum.ForumManager; import org.briarproject.api.forum.ForumPost; -import org.briarproject.api.forum.ForumPostFactory; import org.briarproject.api.forum.ForumPostHeader; import org.briarproject.api.forum.ForumSharingManager; -import org.briarproject.api.identity.AuthorFactory; -import org.briarproject.api.identity.IdentityManager; -import org.briarproject.api.identity.LocalAuthor; -import org.briarproject.api.lifecycle.LifecycleManager; -import org.briarproject.api.sharing.SharingInvitationItem; import org.briarproject.api.sharing.InvitationMessage; +import org.briarproject.api.sharing.SharingInvitationItem; import org.briarproject.api.sync.Group; -import org.briarproject.api.sync.SyncSession; -import org.briarproject.api.sync.SyncSessionFactory; -import org.briarproject.api.sync.ValidationManager.State; -import org.briarproject.api.system.Clock; -import org.briarproject.contact.ContactModule; -import org.briarproject.crypto.CryptoModule; -import org.briarproject.forum.ForumModule; -import org.briarproject.lifecycle.LifecycleModule; -import org.briarproject.properties.PropertiesModule; -import org.briarproject.sharing.SharingModule; -import org.briarproject.sync.SyncModule; -import org.briarproject.transport.TransportModule; -import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.concurrent.TimeoutException; -import java.util.logging.Logger; -import javax.inject.Inject; - -import static org.briarproject.TestPluginsModule.MAX_LATENCY; import static org.briarproject.api.forum.ForumConstants.FORUM_SALT_LENGTH; import static org.briarproject.api.forum.ForumSharingManager.CLIENT_ID; import static org.briarproject.api.sharing.SharingConstants.SHARE_MSG_TYPE_INVITATION; -import static org.briarproject.api.sync.ValidationManager.State.DELIVERED; -import static org.briarproject.api.sync.ValidationManager.State.INVALID; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -public class ForumSharingIntegrationTest extends BriarTestCase { +public class ForumSharingIntegrationTest extends BriarIntegrationTest { - private LifecycleManager lifecycleManager0, lifecycleManager1, lifecycleManager2; - private SyncSessionFactory sync0, sync1, sync2; private ForumManager forumManager0, forumManager1; - private ContactManager contactManager0, contactManager1, contactManager2; - private ContactId contactId0, contactId2, contactId1, contactId21; - private IdentityManager identityManager0, identityManager1, identityManager2; - private LocalAuthor author0, author1, author2; - private Forum forum0; private SharerListener listener0, listener2; private InviteeListener listener1; - - @Inject - Clock clock; - @Inject - AuthorFactory authorFactory; - @Inject - ForumPostFactory forumPostFactory; - @Inject - CryptoComponent cryptoComponent; + private Forum forum0; // objects accessed from background threads need to be volatile private volatile ForumSharingManager forumSharingManager0; private volatile ForumSharingManager forumSharingManager1; private volatile ForumSharingManager forumSharingManager2; private volatile Waiter eventWaiter; - private volatile Waiter msgWaiter; - - private final File testDir = TestUtils.getTestDirectory(); - private final SecretKey master = TestUtils.getSecretKey(); - private final int TIMEOUT = 15000; - private final String SHARER = "Sharer"; - private final String INVITEE = "Invitee"; - private final String SHARER2 = "Sharer2"; - private boolean respond = true; - private static final Logger LOG = - Logger.getLogger(ForumSharingIntegrationTest.class.getName()); - - private ForumSharingIntegrationTestComponent t0, t1, t2; + private boolean respond = true; @Rule - public ExpectedException thrown=ExpectedException.none(); + public ExpectedException thrown = ExpectedException.none(); @Before - public void setUp() { - ForumSharingIntegrationTestComponent component = - DaggerForumSharingIntegrationTestComponent.builder().build(); - component.inject(this); - injectEagerSingletons(component); - - assertTrue(testDir.mkdirs()); - File t0Dir = new File(testDir, SHARER); - t0 = DaggerForumSharingIntegrationTestComponent.builder() - .testDatabaseModule(new TestDatabaseModule(t0Dir)).build(); - injectEagerSingletons(t0); - File t1Dir = new File(testDir, INVITEE); - t1 = DaggerForumSharingIntegrationTestComponent.builder() - .testDatabaseModule(new TestDatabaseModule(t1Dir)).build(); - injectEagerSingletons(t1); - File t2Dir = new File(testDir, SHARER2); - t2 = DaggerForumSharingIntegrationTestComponent.builder() - .testDatabaseModule(new TestDatabaseModule(t2Dir)).build(); - injectEagerSingletons(t2); - - identityManager0 = t0.getIdentityManager(); - identityManager1 = t1.getIdentityManager(); - identityManager2 = t2.getIdentityManager(); - contactManager0 = t0.getContactManager(); - contactManager1 = t1.getContactManager(); - contactManager2 = t2.getContactManager(); - forumManager0 = t0.getForumManager(); - forumManager1 = t1.getForumManager(); - forumSharingManager0 = t0.getForumSharingManager(); - forumSharingManager1 = t1.getForumSharingManager(); - forumSharingManager2 = t2.getForumSharingManager(); - sync0 = t0.getSyncSessionFactory(); - sync1 = t1.getSyncSessionFactory(); - sync2 = t2.getSyncSessionFactory(); - - // initialize waiters fresh for each test - eventWaiter = new Waiter(); - msgWaiter = new Waiter(); - } + @Override + public void setUp() throws Exception { + super.setUp(); - @Test - public void testSuccessfulSharing() throws Exception { - startLifecycles(); - try { - // initialize and let invitee accept all requests - defaultInit(true); + forumManager0 = c0.getForumManager(); + forumManager1 = c1.getForumManager(); + forumSharingManager0 = c0.getForumSharingManager(); + forumSharingManager1 = c1.getForumSharingManager(); + forumSharingManager2 = c2.getForumSharingManager(); - // send invitation - forumSharingManager0 - .sendInvitation(forum0.getId(), contactId1, "Hi!"); + // initialize waiter fresh for each test + eventWaiter = new Waiter(); - // sync first request message - syncToInvitee(); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener1.requestReceived); + addContacts1And2(); + addForumForSharer(); + } - // sync response back - syncToSharer(); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener0.responseReceived); + private void addForumForSharer() throws DbException { + forum0 = forumManager0.addForum("Test Forum"); + } - // forum was added successfully - assertEquals(0, forumSharingManager0.getInvitations().size()); - assertEquals(1, forumManager1.getForums().size()); - - // invitee has one invitation message from sharer - List<InvitationMessage> list = - new ArrayList<>(forumSharingManager1 - .getInvitationMessages(contactId0)); - assertEquals(2, list.size()); - // check other things are alright with the forum message - for (InvitationMessage m : list) { - if (m instanceof ForumInvitationRequest) { - ForumInvitationRequest invitation = - (ForumInvitationRequest) m; - assertFalse(invitation.isAvailable()); - assertEquals(forum0.getName(), invitation.getForumName()); - assertEquals(contactId1, invitation.getContactId()); - assertEquals("Hi!", invitation.getMessage()); - } else { - ForumInvitationResponse response = - (ForumInvitationResponse) m; - assertEquals(contactId0, response.getContactId()); - assertTrue(response.wasAccepted()); - assertTrue(response.isLocal()); - } + @Test + public void testSuccessfulSharing() throws Exception { + // initialize and let invitee accept all requests + listenToEvents(true); + + // send invitation + forumSharingManager0 + .sendInvitation(forum0.getId(), contactId1From0, "Hi!"); + + // sync first request message + sync0To1(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener1.requestReceived); + + // sync response back + sync1To0(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener0.responseReceived); + + // forum was added successfully + assertEquals(0, forumSharingManager0.getInvitations().size()); + assertEquals(1, forumManager1.getForums().size()); + + // invitee has one invitation message from sharer + List<InvitationMessage> list = + new ArrayList<>(forumSharingManager1 + .getInvitationMessages(contactId0From1)); + assertEquals(2, list.size()); + // check other things are alright with the forum message + for (InvitationMessage m : list) { + if (m instanceof ForumInvitationRequest) { + ForumInvitationRequest invitation = + (ForumInvitationRequest) m; + assertFalse(invitation.isAvailable()); + assertEquals(forum0.getName(), invitation.getForumName()); + assertEquals(contactId1From0, invitation.getContactId()); + assertEquals("Hi!", invitation.getMessage()); + } else { + ForumInvitationResponse response = + (ForumInvitationResponse) m; + assertEquals(contactId0From1, response.getContactId()); + assertTrue(response.wasAccepted()); + assertTrue(response.isLocal()); } - // sharer has own invitation message and response - assertEquals(2, - forumSharingManager0.getInvitationMessages(contactId1) - .size()); - // forum can not be shared again - Contact c1 = contactManager0.getContact(contactId1); - assertFalse(forumSharingManager0.canBeShared(forum0.getId(), c1)); - Contact c0 = contactManager1.getContact(contactId0); - assertFalse(forumSharingManager1.canBeShared(forum0.getId(), c0)); - } finally { - stopLifecycles(); } + // sharer has own invitation message and response + assertEquals(2, + forumSharingManager0.getInvitationMessages(contactId1From0) + .size()); + // forum can not be shared again + Contact c1 = contactManager0.getContact(contactId1From0); + assertFalse(forumSharingManager0.canBeShared(forum0.getId(), c1)); + Contact c0 = contactManager1.getContact(contactId0From1); + assertFalse(forumSharingManager1.canBeShared(forum0.getId(), c0)); } @Test public void testDeclinedSharing() throws Exception { - startLifecycles(); - try { - // initialize and let invitee accept all requests - defaultInit(false); - - // send invitation - forumSharingManager0 - .sendInvitation(forum0.getId(), contactId1, null); - - // sync first request message - syncToInvitee(); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener1.requestReceived); - - // sync response back - syncToSharer(); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener0.responseReceived); - - // forum was not added - assertEquals(0, forumSharingManager0.getInvitations().size()); - assertEquals(0, forumManager1.getForums().size()); - // forum is no longer available to invitee who declined - assertEquals(0, forumSharingManager1.getInvitations().size()); - - // invitee has one invitation message from sharer and one response - List<InvitationMessage> list = - new ArrayList<>(forumSharingManager1 - .getInvitationMessages(contactId0)); - assertEquals(2, list.size()); - // check things are alright with the forum message - for (InvitationMessage m : list) { - if (m instanceof ForumInvitationRequest) { - ForumInvitationRequest invitation = - (ForumInvitationRequest) m; - assertFalse(invitation.isAvailable()); - assertEquals(forum0.getName(), invitation.getForumName()); - assertEquals(contactId1, invitation.getContactId()); - assertEquals(null, invitation.getMessage()); - } else { - ForumInvitationResponse response = - (ForumInvitationResponse) m; - assertEquals(contactId0, response.getContactId()); - assertFalse(response.wasAccepted()); - assertTrue(response.isLocal()); - } + // initialize and let invitee accept all requests + listenToEvents(false); + + // send invitation + forumSharingManager0 + .sendInvitation(forum0.getId(), contactId1From0, null); + + // sync first request message + sync0To1(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener1.requestReceived); + + // sync response back + sync1To0(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener0.responseReceived); + + // forum was not added + assertEquals(0, forumSharingManager0.getInvitations().size()); + assertEquals(0, forumManager1.getForums().size()); + // forum is no longer available to invitee who declined + assertEquals(0, forumSharingManager1.getInvitations().size()); + + // invitee has one invitation message from sharer and one response + List<InvitationMessage> list = + new ArrayList<>(forumSharingManager1 + .getInvitationMessages(contactId0From1)); + assertEquals(2, list.size()); + // check things are alright with the forum message + for (InvitationMessage m : list) { + if (m instanceof ForumInvitationRequest) { + ForumInvitationRequest invitation = + (ForumInvitationRequest) m; + assertFalse(invitation.isAvailable()); + assertEquals(forum0.getName(), invitation.getForumName()); + assertEquals(contactId1From0, invitation.getContactId()); + assertEquals(null, invitation.getMessage()); + } else { + ForumInvitationResponse response = + (ForumInvitationResponse) m; + assertEquals(contactId0From1, response.getContactId()); + assertFalse(response.wasAccepted()); + assertTrue(response.isLocal()); } - // sharer has own invitation message and response - assertEquals(2, - forumSharingManager0.getInvitationMessages(contactId1) - .size()); - // forum can be shared again - Contact c1 = contactManager0.getContact(contactId1); - assertTrue(forumSharingManager0.canBeShared(forum0.getId(), c1)); - } finally { - stopLifecycles(); } + // sharer has own invitation message and response + assertEquals(2, + forumSharingManager0.getInvitationMessages(contactId1From0) + .size()); + // forum can be shared again + Contact c1 = contactManager0.getContact(contactId1From0); + assertTrue(forumSharingManager0.canBeShared(forum0.getId(), c1)); } @Test public void testInviteeLeavesAfterFinished() throws Exception { - startLifecycles(); - try { - // initialize and let invitee accept all requests - defaultInit(true); - - // send invitation - forumSharingManager0 - .sendInvitation(forum0.getId(), contactId1, "Hi!"); - - // sync first request message - syncToInvitee(); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener1.requestReceived); - - // sync response back - syncToSharer(); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener0.responseReceived); - - // forum was added successfully - assertEquals(0, forumSharingManager0.getInvitations().size()); - assertEquals(1, forumManager1.getForums().size()); - assertTrue(forumManager1.getForums().contains(forum0)); - - // sharer shares forum with invitee - Contact c1 = contactManager0.getContact(contactId1); - assertTrue(forumSharingManager0.getSharedWith(forum0.getId()) - .contains(c1)); - // invitee gets forum shared by sharer - Contact contact0 = contactManager1.getContact(contactId1); - assertTrue(forumSharingManager1.getSharedBy(forum0.getId()) - .contains(contact0)); - - // invitee un-subscribes from forum - forumManager1.removeForum(forum0); - - // send leave message to sharer - syncToSharer(); - - // forum is gone - assertEquals(0, forumSharingManager0.getInvitations().size()); - assertEquals(0, forumManager1.getForums().size()); - - // sharer no longer shares forum with invitee - assertFalse(forumSharingManager0.getSharedWith(forum0.getId()) - .contains(c1)); - // invitee no longer gets forum shared by sharer - assertFalse(forumSharingManager1.getSharedBy(forum0.getId()) - .contains(contact0)); - // forum can be shared again - assertTrue(forumSharingManager0.canBeShared(forum0.getId(), c1)); - Contact c0 = contactManager1.getContact(contactId0); - assertTrue(forumSharingManager1.canBeShared(forum0.getId(), c0)); - } finally { - stopLifecycles(); - } + // initialize and let invitee accept all requests + listenToEvents(true); + + // send invitation + forumSharingManager0 + .sendInvitation(forum0.getId(), contactId1From0, "Hi!"); + + // sync first request message + sync0To1(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener1.requestReceived); + + // sync response back + sync1To0(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener0.responseReceived); + + // forum was added successfully + assertEquals(0, forumSharingManager0.getInvitations().size()); + assertEquals(1, forumManager1.getForums().size()); + assertTrue(forumManager1.getForums().contains(forum0)); + + // sharer shares forum with invitee + Contact c1 = contactManager0.getContact(contactId1From0); + assertTrue(forumSharingManager0.getSharedWith(forum0.getId()) + .contains(c1)); + // invitee gets forum shared by sharer + Contact contact0 = contactManager1.getContact(contactId1From0); + assertTrue(forumSharingManager1.getSharedBy(forum0.getId()) + .contains(contact0)); + + // invitee un-subscribes from forum + forumManager1.removeForum(forum0); + + // send leave message to sharer + sync1To0(1, true); + + // forum is gone + assertEquals(0, forumSharingManager0.getInvitations().size()); + assertEquals(0, forumManager1.getForums().size()); + + // sharer no longer shares forum with invitee + assertFalse(forumSharingManager0.getSharedWith(forum0.getId()) + .contains(c1)); + // invitee no longer gets forum shared by sharer + assertFalse(forumSharingManager1.getSharedBy(forum0.getId()) + .contains(contact0)); + // forum can be shared again + assertTrue(forumSharingManager0.canBeShared(forum0.getId(), c1)); + Contact c0 = contactManager1.getContact(contactId0From1); + assertTrue(forumSharingManager1.canBeShared(forum0.getId(), c0)); } @Test public void testSharerLeavesAfterFinished() throws Exception { - startLifecycles(); - try { - // initialize and let invitee accept all requests - defaultInit(true); - - // send invitation - forumSharingManager0 - .sendInvitation(forum0.getId(), contactId1, null); - - // sync first request message - syncToInvitee(); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener1.requestReceived); - - // sync response back - syncToSharer(); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener0.responseReceived); - - // forum was added successfully - assertEquals(0, forumSharingManager0.getInvitations().size()); - assertEquals(1, forumManager1.getForums().size()); - assertTrue(forumManager1.getForums().contains(forum0)); - - // sharer shares forum with invitee - Contact c1 = contactManager0.getContact(contactId1); - assertTrue(forumSharingManager0.getSharedWith(forum0.getId()) - .contains(c1)); - // invitee gets forum shared by sharer - Contact contact0 = contactManager1.getContact(contactId1); - assertTrue(forumSharingManager1.getSharedBy(forum0.getId()) - .contains(contact0)); - - // sharer un-subscribes from forum - forumManager0.removeForum(forum0); - - // send leave message to invitee - syncToInvitee(); - - // forum is gone for sharer, but not invitee - assertEquals(0, forumManager0.getForums().size()); - assertEquals(1, forumManager1.getForums().size()); - - // invitee no longer shares forum with sharer - Contact c0 = contactManager1.getContact(contactId0); - assertFalse(forumSharingManager1.getSharedWith(forum0.getId()) - .contains(c0)); - // sharer no longer gets forum shared by invitee - assertFalse(forumSharingManager1.getSharedBy(forum0.getId()) - .contains(contact0)); - // forum can be shared again - assertTrue(forumSharingManager1.canBeShared(forum0.getId(), c0)); - } finally { - stopLifecycles(); - } + // initialize and let invitee accept all requests + listenToEvents(true); + + // send invitation + forumSharingManager0 + .sendInvitation(forum0.getId(), contactId1From0, null); + + // sync first request message + sync0To1(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener1.requestReceived); + + // sync response back + sync1To0(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener0.responseReceived); + + // forum was added successfully + assertEquals(0, forumSharingManager0.getInvitations().size()); + assertEquals(1, forumManager1.getForums().size()); + assertTrue(forumManager1.getForums().contains(forum0)); + + // sharer shares forum with invitee + Contact c1 = contactManager0.getContact(contactId1From0); + assertTrue(forumSharingManager0.getSharedWith(forum0.getId()) + .contains(c1)); + // invitee gets forum shared by sharer + Contact contact0 = contactManager1.getContact(contactId1From0); + assertTrue(forumSharingManager1.getSharedBy(forum0.getId()) + .contains(contact0)); + + // sharer un-subscribes from forum + forumManager0.removeForum(forum0); + + // send leave message to invitee + sync0To1(1, true); + + // forum is gone for sharer, but not invitee + assertEquals(0, forumManager0.getForums().size()); + assertEquals(1, forumManager1.getForums().size()); + + // invitee no longer shares forum with sharer + Contact c0 = contactManager1.getContact(contactId0From1); + assertFalse(forumSharingManager1.getSharedWith(forum0.getId()) + .contains(c0)); + // sharer no longer gets forum shared by invitee + assertFalse(forumSharingManager1.getSharedBy(forum0.getId()) + .contains(contact0)); + // forum can be shared again + assertTrue(forumSharingManager1.canBeShared(forum0.getId(), c0)); } @Test public void testSharerLeavesBeforeResponse() throws Exception { - startLifecycles(); - try { - // initialize except event listeners - defaultInit(true); + // initialize except event listeners + listenToEvents(true); - // send invitation - forumSharingManager0 - .sendInvitation(forum0.getId(), contactId1, null); + // send invitation + forumSharingManager0 + .sendInvitation(forum0.getId(), contactId1From0, null); - // sharer un-subscribes from forum - forumManager0.removeForum(forum0); + // sharer un-subscribes from forum + forumManager0.removeForum(forum0); - // prevent invitee response before syncing messages - respond = false; + // prevent invitee response before syncing messages + respond = false; - // sync first request message and leave message - deliverMessage(sync0, contactId0, sync1, contactId1, 2, - "Sharer to Invitee"); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener1.requestReceived); + // sync first request message and leave message + sync0To1(2, true); + + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener1.requestReceived); - // ensure that invitee has no forum invitations available - assertEquals(0, forumSharingManager1.getInvitations().size()); - assertEquals(0, forumManager1.getForums().size()); + // ensure that invitee has no forum invitations available + assertEquals(0, forumSharingManager1.getInvitations().size()); + assertEquals(0, forumManager1.getForums().size()); - // Try again, this time allow the response - addForumForSharer(); - respond = true; + // Try again, this time allow the response + addForumForSharer(); + respond = true; - // send invitation - forumSharingManager0 - .sendInvitation(forum0.getId(), contactId1, null); + // send invitation + forumSharingManager0 + .sendInvitation(forum0.getId(), contactId1From0, null); - // sharer un-subscribes from forum - forumManager0.removeForum(forum0); + // sharer un-subscribes from forum + forumManager0.removeForum(forum0); - // sync first request message and leave message - deliverMessage(sync0, contactId0, sync1, contactId1, 2, - "Sharer to Invitee"); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener1.requestReceived); + // sync first request message and leave message + sync0To1(2, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener1.requestReceived); - // ensure that invitee has no forum invitations available - assertEquals(0, forumSharingManager1.getInvitations().size()); - assertEquals(1, forumManager1.getForums().size()); - } finally { - stopLifecycles(); - } + // ensure that invitee has no forum invitations available + assertEquals(0, forumSharingManager1.getInvitations().size()); + assertEquals(1, forumManager1.getForums().size()); } @Test public void testSessionIdReuse() throws Exception { - startLifecycles(); - try { - // initialize and let invitee accept all requests - defaultInit(true); - - // send invitation - forumSharingManager0 - .sendInvitation(forum0.getId(), contactId1, "Hi!"); - - // sync first request message - syncToInvitee(); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener1.requestReceived); - - // sync response back - syncToSharer(); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener0.responseReceived); - - // forum was added successfully - assertEquals(1, forumManager1.getForums().size()); - - // reset event received state - listener1.requestReceived = false; - - // get SessionId from invitation - List<InvitationMessage> list = new ArrayList<>( - forumSharingManager1 - .getInvitationMessages(contactId0)); - assertEquals(2, list.size()); - InvitationMessage msg = list.get(0); - SessionId sessionId = msg.getSessionId(); - assertEquals(sessionId, list.get(1).getSessionId()); - - // get all sorts of stuff needed to send a message - DatabaseComponent db = t0.getDatabaseComponent(); - MessageQueueManager queue = t0.getMessageQueueManager(); - Contact c1 = contactManager0.getContact(contactId1); - ContactGroupFactory groupFactory = t0.getContactGroupFactory(); - Group group = groupFactory.createContactGroup(CLIENT_ID, c1); - long time = clock.currentTimeMillis(); - BdfList bodyList = BdfList.of(SHARE_MSG_TYPE_INVITATION, - sessionId.getBytes(), - TestUtils.getRandomString(42), - TestUtils.getRandomBytes(FORUM_SALT_LENGTH) - ); - byte[] body = t0.getClientHelper().toByteArray(bodyList); - - // add the message to the queue - Transaction txn = db.startTransaction(false); - try { - queue.sendMessage(txn, group, time, body, new Metadata()); - db.commitTransaction(txn); - } finally { - db.endTransaction(txn); - } + // initialize and let invitee accept all requests + listenToEvents(true); + + // send invitation + forumSharingManager0 + .sendInvitation(forum0.getId(), contactId1From0, "Hi!"); + + // sync first request message + sync0To1(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener1.requestReceived); + + // sync response back + sync1To0(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener0.responseReceived); + + // forum was added successfully + assertEquals(1, forumManager1.getForums().size()); + + // reset event received state + listener1.requestReceived = false; + + // get SessionId from invitation + List<InvitationMessage> list = new ArrayList<>( + forumSharingManager1 + .getInvitationMessages(contactId0From1)); + assertEquals(2, list.size()); + InvitationMessage msg = list.get(0); + SessionId sessionId = msg.getSessionId(); + assertEquals(sessionId, list.get(1).getSessionId()); + + // get all sorts of stuff needed to send a message + MessageQueueManager queue = c0.getMessageQueueManager(); + Contact c1 = contactManager0.getContact(contactId1From0); + Group group = contactGroupFactory.createContactGroup(CLIENT_ID, c1); + long time = clock.currentTimeMillis(); + BdfList bodyList = BdfList.of(SHARE_MSG_TYPE_INVITATION, + sessionId.getBytes(), + TestUtils.getRandomString(42), + TestUtils.getRandomBytes(FORUM_SALT_LENGTH) + ); + byte[] body = clientHelper.toByteArray(bodyList); - // actually send the message - syncToInvitee(); - // make sure there was no new request received - assertFalse(listener1.requestReceived); + // add the message to the queue + Transaction txn = db0.startTransaction(false); + try { + queue.sendMessage(txn, group, time, body, new Metadata()); + db0.commitTransaction(txn); } finally { - stopLifecycles(); + db0.endTransaction(txn); } + + // actually send the message + sync0To1(1, false); + // make sure there was no new request received + assertFalse(listener1.requestReceived); } @Test public void testSharingSameForumWithEachOther() throws Exception { - startLifecycles(); - try { - // initialize and let invitee accept all requests - defaultInit(true); - - // send invitation - forumSharingManager0 - .sendInvitation(forum0.getId(), contactId1, "Hi!"); + // initialize and let invitee accept all requests + listenToEvents(true); + + // send invitation + forumSharingManager0 + .sendInvitation(forum0.getId(), contactId1From0, "Hi!"); + + // sync first request message + sync0To1(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener1.requestReceived); + + // sync response back + sync1To0(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener0.responseReceived); + + // forum was added successfully + assertEquals(1, forumManager1.getForums().size()); + assertEquals(2, + forumSharingManager0.getInvitationMessages(contactId1From0) + .size()); + + // invitee now shares same forum back + forumSharingManager1.sendInvitation(forum0.getId(), + contactId0From1, + "I am re-sharing this forum with you."); + + // sync re-share invitation + sync1To0(1, false); + + // make sure that no new request was received + assertFalse(listener0.requestReceived); + assertEquals(2, + forumSharingManager0.getInvitationMessages(contactId1From0) + .size()); + assertEquals(0, forumSharingManager0.getInvitations().size()); + } - // sync first request message - syncToInvitee(); + @Test + public void testSharingSameForumWithEachOtherAtSameTime() throws Exception { + // initialize and let invitee accept all requests + listenToEvents(true); + + // invitee adds the same forum + Transaction txn = db1.startTransaction(false); + db1.addGroup(txn, forum0.getGroup()); + db1.commitTransaction(txn); + db1.endTransaction(txn); + + // send invitation + forumSharingManager0 + .sendInvitation(forum0.getId(), contactId1From0, "Hi!"); + + // invitee now shares same forum back + forumSharingManager1.sendInvitation(forum0.getId(), + contactId0From1, "I am re-sharing this forum with you."); + + // find out who should be Alice, because of random keys + Bytes key0 = new Bytes(author0.getPublicKey()); + Bytes key1 = new Bytes(author1.getPublicKey()); + + // only now sync first request message + boolean alice = key1.compareTo(key0) < 0; + if (alice) { + sync0To1(1, false); + assertFalse(listener1.requestReceived); + } else { + sync0To1(1, true); eventWaiter.await(TIMEOUT, 1); assertTrue(listener1.requestReceived); + } - // sync response back - syncToSharer(); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener0.responseReceived); - - // forum was added successfully - assertEquals(1, forumManager1.getForums().size()); - assertEquals(2, - forumSharingManager0.getInvitationMessages(contactId1) - .size()); - - // invitee now shares same forum back - forumSharingManager1.sendInvitation(forum0.getId(), - contactId0, - "I am re-sharing this forum with you."); - - // sync re-share invitation - syncToSharer(); - - // make sure that no new request was received + // sync second invitation + alice = key0.compareTo(key1) < 0; + if (alice) { + sync1To0(1, false); assertFalse(listener0.requestReceived); - assertEquals(2, - forumSharingManager0.getInvitationMessages(contactId1) - .size()); - assertEquals(0, forumSharingManager0.getInvitations().size()); - } finally { - stopLifecycles(); - } - } - @Test - public void testSharingSameForumWithEachOtherAtSameTime() throws Exception { - startLifecycles(); - try { - // initialize and let invitee accept all requests - defaultInit(true); - - // invitee adds the same forum - DatabaseComponent db1 = t1.getDatabaseComponent(); - Transaction txn = db1.startTransaction(false); - db1.addGroup(txn, forum0.getGroup()); - db1.commitTransaction(txn); - db1.endTransaction(txn); - - // send invitation - forumSharingManager0 - .sendInvitation(forum0.getId(), contactId1, "Hi!"); - - // invitee now shares same forum back - forumSharingManager1.sendInvitation(forum0.getId(), - contactId0, "I am re-sharing this forum with you."); - - // find out who should be Alice, because of random keys - Bytes key0 = new Bytes(author0.getPublicKey()); - Bytes key1 = new Bytes(author1.getPublicKey()); - - // only now sync first request message - boolean alice = key1.compareTo(key0) < 0; - syncToInvitee(); - if (alice) { - assertFalse(listener1.requestReceived); - } else { - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener1.requestReceived); - } + // sharer did not receive request, but response to own request + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener0.responseReceived); - // sync second invitation - alice = key0.compareTo(key1) < 0; - syncToSharer(); - if (alice) { - assertFalse(listener0.requestReceived); + assertEquals(2, forumSharingManager0 + .getInvitationMessages(contactId1From0).size()); + assertEquals(3, forumSharingManager1 + .getInvitationMessages(contactId0From1).size()); + } else { + sync1To0(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener0.requestReceived); - // sharer did not receive request, but response to own request - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener0.responseReceived); + // send response from sharer to invitee and make sure it arrived + sync0To1(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener1.responseReceived); - assertEquals(2, forumSharingManager0 - .getInvitationMessages(contactId1).size()); - assertEquals(3, forumSharingManager1 - .getInvitationMessages(contactId0).size()); - } else { - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener0.requestReceived); - - // send response from sharer to invitee and make sure it arrived - syncToInvitee(); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener1.responseReceived); - - assertEquals(3, forumSharingManager0 - .getInvitationMessages(contactId1).size()); - assertEquals(2, forumSharingManager1 - .getInvitationMessages(contactId0).size()); - } - } finally { - stopLifecycles(); + assertEquals(3, forumSharingManager0 + .getInvitationMessages(contactId1From0).size()); + assertEquals(2, forumSharingManager1 + .getInvitationMessages(contactId0From1).size()); } } @Test public void testContactRemoved() throws Exception { - startLifecycles(); - try { - // initialize and let invitee accept all requests - defaultInit(true); - - // send invitation - forumSharingManager0 - .sendInvitation(forum0.getId(), contactId1, "Hi!"); - - // sync first request message - syncToInvitee(); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener1.requestReceived); - - // sync response back - syncToSharer(); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener0.responseReceived); - - // forum was added successfully - assertEquals(1, forumManager1.getForums().size()); - assertEquals(1, - forumSharingManager0.getSharedWith(forum0.getId()).size()); - - // remember SessionId from invitation - List<InvitationMessage> list = new ArrayList<>( - forumSharingManager1 - .getInvitationMessages(contactId0)); - assertEquals(2, list.size()); - InvitationMessage msg = list.get(0); - SessionId sessionId = msg.getSessionId(); - assertEquals(sessionId, list.get(1).getSessionId()); - - // contacts now remove each other - contactManager0.removeContact(contactId1); - contactManager2.removeContact(contactId21); - contactManager1.removeContact(contactId0); - contactManager1.removeContact(contactId2); - - // make sure sharer does share the forum with nobody now - assertEquals(0, - forumSharingManager0.getSharedWith(forum0.getId()).size()); - - // contacts add each other again - addDefaultContacts(); - - // get all sorts of stuff needed to send a message - DatabaseComponent db = t0.getDatabaseComponent(); - MessageQueueManager queue = t0.getMessageQueueManager(); - Contact c1 = contactManager0.getContact(contactId1); - ContactGroupFactory groupFactory = t0.getContactGroupFactory(); - Group group = groupFactory.createContactGroup(CLIENT_ID, c1); - long time = clock.currentTimeMillis(); - - // construct a new message re-using the old SessionId - BdfList bodyList = BdfList.of(SHARE_MSG_TYPE_INVITATION, - sessionId.getBytes(), - TestUtils.getRandomString(42), - TestUtils.getRandomBytes(FORUM_SALT_LENGTH) - ); - byte[] body = t0.getClientHelper().toByteArray(bodyList); - - // add the message to the queue - Transaction txn = db.startTransaction(false); - try { - queue.sendMessage(txn, group, time, body, new Metadata()); - db.commitTransaction(txn); - } finally { - db.endTransaction(txn); - } + // initialize and let invitee accept all requests + listenToEvents(true); + + // send invitation + forumSharingManager0 + .sendInvitation(forum0.getId(), contactId1From0, "Hi!"); + + // sync first request message + sync0To1(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener1.requestReceived); + + // sync response back + sync1To0(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener0.responseReceived); + + // forum was added successfully + assertEquals(1, forumManager1.getForums().size()); + assertEquals(1, + forumSharingManager0.getSharedWith(forum0.getId()).size()); + + // remember SessionId from invitation + List<InvitationMessage> list = new ArrayList<>( + forumSharingManager1 + .getInvitationMessages(contactId0From1)); + assertEquals(2, list.size()); + InvitationMessage msg = list.get(0); + SessionId sessionId = msg.getSessionId(); + assertEquals(sessionId, list.get(1).getSessionId()); + + // contacts now remove each other + removeAllContacts(); + + // make sure sharer does share the forum with nobody now + assertEquals(0, + forumSharingManager0.getSharedWith(forum0.getId()).size()); + + // contacts add each other again + addDefaultContacts(); + addContacts1And2(); + + // get all sorts of stuff needed to send a message + MessageQueueManager queue = c0.getMessageQueueManager(); + Contact c1 = contactManager0.getContact(contactId1From0); + Group group = contactGroupFactory.createContactGroup(CLIENT_ID, c1); + long time = clock.currentTimeMillis(); + + // construct a new message re-using the old SessionId + BdfList bodyList = BdfList.of(SHARE_MSG_TYPE_INVITATION, + sessionId.getBytes(), + TestUtils.getRandomString(42), + TestUtils.getRandomBytes(FORUM_SALT_LENGTH) + ); + byte[] body = clientHelper.toByteArray(bodyList); - // actually send the message - syncToInvitee(); - eventWaiter.await(TIMEOUT, 1); - // make sure the new request was received with the same sessionId - // as proof that the state got deleted along with contacts - assertTrue(listener1.requestReceived); + // add the message to the queue + Transaction txn = db0.startTransaction(false); + try { + queue.sendMessage(txn, group, time, body, new Metadata()); + db0.commitTransaction(txn); } finally { - stopLifecycles(); + db0.endTransaction(txn); } + + // actually send the message + sync0To1(1, true); + eventWaiter.await(TIMEOUT, 1); + // make sure the new request was received with the same sessionId + // as proof that the state got deleted along with contacts + assertTrue(listener1.requestReceived); } @Test public void testTwoContactsShareSameForum() throws Exception { - startLifecycles(); - try { - // initialize - getDefaultIdentities(); - addDefaultContacts(); - addForumForSharer(); - - // second sharer adds the same forum - DatabaseComponent db2 = t2.getDatabaseComponent(); - Transaction txn = db2.startTransaction(false); - db2.addGroup(txn, forum0.getGroup()); - db2.commitTransaction(txn); - db2.endTransaction(txn); - - // add listeners - listener0 = new SharerListener(); - t0.getEventBus().addListener(listener0); - listener1 = new InviteeListener(true, false); - t1.getEventBus().addListener(listener1); - listener2 = new SharerListener(); - t2.getEventBus().addListener(listener2); - - // send invitation - forumSharingManager0 - .sendInvitation(forum0.getId(), contactId1, "Hi!"); - // sync first request message - syncToInvitee(); - - // second sharer sends invitation for same forum - forumSharingManager2 - .sendInvitation(forum0.getId(), contactId1, null); - // sync second request message - deliverMessage(sync2, contactId2, sync1, contactId1, 1, - "Sharer2 to Invitee"); - - // make sure we now have two invitations to the same forum available - Collection<SharingInvitationItem> forums = - forumSharingManager1.getInvitations(); - assertEquals(1, forums.size()); - assertEquals(2, forums.iterator().next().getNewSharers().size()); - assertEquals(forum0, forums.iterator().next().getShareable()); - assertEquals(2, - forumSharingManager1.getSharedBy(forum0.getId()).size()); - - // make sure both sharers actually share the forum - Collection<Contact> contacts = - forumSharingManager1.getSharedBy(forum0.getId()); - assertEquals(2, contacts.size()); - - // answer second request - Contact c2 = contactManager1.getContact(contactId2); - forumSharingManager1.respondToInvitation(forum0, c2, true); - // sync response - deliverMessage(sync1, contactId21, sync2, contactId2, 1, - "Invitee to Sharer2"); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener2.responseReceived); - - // answer first request - Contact c0 = - contactManager1.getContact(contactId0); - forumSharingManager1.respondToInvitation(forum0, c0, true); - // sync response - syncToSharer(); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener0.responseReceived); - } finally { - stopLifecycles(); - } + // second sharer adds the same forum + Transaction txn = db2.startTransaction(false); + db2.addGroup(txn, forum0.getGroup()); + db2.commitTransaction(txn); + db2.endTransaction(txn); + + // add listeners + listener0 = new SharerListener(); + c0.getEventBus().addListener(listener0); + listener1 = new InviteeListener(true, false); + c1.getEventBus().addListener(listener1); + listener2 = new SharerListener(); + c2.getEventBus().addListener(listener2); + + // send invitation + forumSharingManager0 + .sendInvitation(forum0.getId(), contactId1From0, "Hi!"); + // sync first request message + sync0To1(1, true); + + // second sharer sends invitation for same forum + assertTrue(contactId1From2 != null); + forumSharingManager2 + .sendInvitation(forum0.getId(), contactId1From2, null); + // sync second request message + sync2To1(1, true); + + // make sure we now have two invitations to the same forum available + Collection<SharingInvitationItem> forums = + forumSharingManager1.getInvitations(); + assertEquals(1, forums.size()); + assertEquals(2, forums.iterator().next().getNewSharers().size()); + assertEquals(forum0, forums.iterator().next().getShareable()); + assertEquals(2, + forumSharingManager1.getSharedBy(forum0.getId()).size()); + + // make sure both sharers actually share the forum + Collection<Contact> contacts = + forumSharingManager1.getSharedBy(forum0.getId()); + assertEquals(2, contacts.size()); + + // answer second request + Contact contact2From1 = contactManager1.getContact(contactId2From1); + forumSharingManager1.respondToInvitation(forum0, contact2From1, true); + // sync response + sync1To2(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener2.responseReceived); + + // answer first request + Contact c0 = + contactManager1.getContact(contactId0From1); + forumSharingManager1.respondToInvitation(forum0, c0, true); + // sync response + sync1To0(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener0.responseReceived); } @Test public void testSyncAfterReSharing() throws Exception { - startLifecycles(); - try { - // initialize and let invitee accept all requests - defaultInit(true); - - // send invitation - forumSharingManager0 - .sendInvitation(forum0.getId(), contactId1, "Hi!"); - - // sync first request message - syncToInvitee(); - eventWaiter.await(TIMEOUT, 1); - - // sync response back - syncToSharer(); - eventWaiter.await(TIMEOUT, 1); - - // sharer posts into the forum - long time = clock.currentTimeMillis(); - String body = TestUtils.getRandomString(42); - ForumPost p = forumPostFactory - .createPost(forum0.getId(), time, null, author0, - body); - forumManager0.addLocalPost(p); - - // sync forum post - syncToInvitee(); - - // make sure forum post arrived - Collection<ForumPostHeader> headers = - forumManager1.getPostHeaders(forum0.getId()); - assertEquals(1, headers.size()); - ForumPostHeader header = headers.iterator().next(); - assertEquals(p.getMessage().getId(), header.getId()); - assertEquals(author0, header.getAuthor()); - - // now invitee creates a post - time = clock.currentTimeMillis(); - body = TestUtils.getRandomString(42); - p = forumPostFactory - .createPost(forum0.getId(), time, null, author1, - body); - forumManager1.addLocalPost(p); - - // sync forum post - syncToSharer(); - - // make sure forum post arrived - headers = forumManager1.getPostHeaders(forum0.getId()); - assertEquals(2, headers.size()); - boolean found = false; - for (ForumPostHeader h : headers) { - if (p.getMessage().getId().equals(h.getId())) { - found = true; - assertEquals(author1, h.getAuthor()); - } + // initialize and let invitee accept all requests + listenToEvents(true); + + // send invitation + forumSharingManager0 + .sendInvitation(forum0.getId(), contactId1From0, "Hi!"); + + // sync first request message + sync0To1(1, true); + eventWaiter.await(TIMEOUT, 1); + + // sync response back + sync1To0(1, true); + eventWaiter.await(TIMEOUT, 1); + + // sharer posts into the forum + long time = clock.currentTimeMillis(); + String body = TestUtils.getRandomString(42); + ForumPost p = forumPostFactory + .createPost(forum0.getId(), time, null, author0, + body); + forumManager0.addLocalPost(p); + + // sync forum post + sync0To1(1, true); + + // make sure forum post arrived + Collection<ForumPostHeader> headers = + forumManager1.getPostHeaders(forum0.getId()); + assertEquals(1, headers.size()); + ForumPostHeader header = headers.iterator().next(); + assertEquals(p.getMessage().getId(), header.getId()); + assertEquals(author0, header.getAuthor()); + + // now invitee creates a post + time = clock.currentTimeMillis(); + body = TestUtils.getRandomString(42); + p = forumPostFactory + .createPost(forum0.getId(), time, null, author1, + body); + forumManager1.addLocalPost(p); + + // sync forum post + sync1To0(1, true); + + // make sure forum post arrived + headers = forumManager1.getPostHeaders(forum0.getId()); + assertEquals(2, headers.size()); + boolean found = false; + for (ForumPostHeader h : headers) { + if (p.getMessage().getId().equals(h.getId())) { + found = true; + assertEquals(author1, h.getAuthor()); } - assertTrue(found); - - // contacts remove each other - contactManager0.removeContact(contactId1); - contactManager1.removeContact(contactId0); - contactManager1.removeContact(contactId2); - contactManager2.removeContact(contactId21); - - // contacts add each other back - addDefaultContacts(); - - // send invitation again - forumSharingManager0 - .sendInvitation(forum0.getId(), contactId1, "Hi!"); - - // sync first request message - syncToInvitee(); - eventWaiter.await(TIMEOUT, 1); + } + assertTrue(found); - // sync response back - syncToSharer(); - eventWaiter.await(TIMEOUT, 1); + // contacts remove each other + removeAllContacts(); - // now invitee creates a post - time = clock.currentTimeMillis(); - body = TestUtils.getRandomString(42); - p = forumPostFactory - .createPost(forum0.getId(), time, null, author1, - body); - forumManager1.addLocalPost(p); - - // sync forum post - syncToSharer(); - - // make sure forum post arrived - headers = forumManager1.getPostHeaders(forum0.getId()); - assertEquals(3, headers.size()); - found = false; - for (ForumPostHeader h : headers) { - if (p.getMessage().getId().equals(h.getId())) { - found = true; - assertEquals(author1, h.getAuthor()); - } + // contacts add each other back + addDefaultContacts(); + addContacts1And2(); + + // send invitation again + forumSharingManager0 + .sendInvitation(forum0.getId(), contactId1From0, "Hi!"); + + // sync first request message + sync0To1(1, true); + eventWaiter.await(TIMEOUT, 1); + + // sync response back + sync1To0(1, true); + eventWaiter.await(TIMEOUT, 1); + + // now invitee creates a post + time = clock.currentTimeMillis(); + body = TestUtils.getRandomString(42); + p = forumPostFactory + .createPost(forum0.getId(), time, null, author1, + body); + forumManager1.addLocalPost(p); + + // sync forum post + sync1To0(1, true); + + // make sure forum post arrived + headers = forumManager1.getPostHeaders(forum0.getId()); + assertEquals(3, headers.size()); + found = false; + for (ForumPostHeader h : headers) { + if (p.getMessage().getId().equals(h.getId())) { + found = true; + assertEquals(author1, h.getAuthor()); } - assertTrue(found); - } finally { - stopLifecycles(); } - } - - - @After - public void tearDown() throws InterruptedException { - TestUtils.deleteTestDirectory(testDir); + assertTrue(found); } private class SharerListener implements EventListener { @@ -917,17 +759,7 @@ public class ForumSharingIntegrationTest extends BriarTestCase { @Override public void eventOccurred(Event e) { - if (e instanceof MessageStateChangedEvent) { - MessageStateChangedEvent event = (MessageStateChangedEvent) e; - State s = event.getState(); - if ((s == DELIVERED || s == INVALID) && !event.isLocal()) { - LOG.info("TEST: Sharer received message"); - msgWaiter.resume(); - } - } else if (e instanceof ForumInvitationResponseReceivedEvent) { - ForumInvitationResponseReceivedEvent event = - (ForumInvitationResponseReceivedEvent) e; - eventWaiter.assertEquals(contactId1, event.getContactId()); + if (e instanceof ForumInvitationResponseReceivedEvent) { responseReceived = true; eventWaiter.resume(); } @@ -935,11 +767,11 @@ public class ForumSharingIntegrationTest extends BriarTestCase { else if (e instanceof ForumInvitationReceivedEvent) { ForumInvitationReceivedEvent event = (ForumInvitationReceivedEvent) e; - eventWaiter.assertEquals(contactId1, event.getContactId()); + eventWaiter.assertEquals(contactId1From0, event.getContactId()); requestReceived = true; Forum f = event.getShareable(); try { - Contact c = contactManager0.getContact(contactId1); + Contact c = contactManager0.getContact(contactId1From0); forumSharingManager0.respondToInvitation(f, c, true); } catch (DbException ex) { eventWaiter.rethrow(ex); @@ -968,14 +800,7 @@ public class ForumSharingIntegrationTest extends BriarTestCase { @Override public void eventOccurred(Event e) { - if (e instanceof MessageStateChangedEvent) { - MessageStateChangedEvent event = (MessageStateChangedEvent) e; - State s = event.getState(); - if ((s == DELIVERED || s == INVALID) && !event.isLocal()) { - LOG.info("TEST: Invitee received message"); - msgWaiter.resume(); - } - } else if (e instanceof ForumInvitationReceivedEvent) { + if (e instanceof ForumInvitationReceivedEvent) { ForumInvitationReceivedEvent event = (ForumInvitationReceivedEvent) e; requestReceived = true; @@ -988,11 +813,12 @@ public class ForumSharingIntegrationTest extends BriarTestCase { forumSharingManager1.getInvitations().iterator() .next(); eventWaiter.assertEquals(f, invitation.getShareable()); - if (respond) { - Contact c = - contactManager1.getContact(event.getContactId()); - forumSharingManager1.respondToInvitation(f, c, accept); - } + if (respond) { + Contact c = + contactManager1 + .getContact(event.getContactId()); + forumSharingManager1.respondToInvitation(f, c, accept); + } } catch (DbException ex) { eventWaiter.rethrow(ex); } finally { @@ -1003,131 +829,20 @@ public class ForumSharingIntegrationTest extends BriarTestCase { else if (e instanceof ForumInvitationResponseReceivedEvent) { ForumInvitationResponseReceivedEvent event = (ForumInvitationResponseReceivedEvent) e; - eventWaiter.assertEquals(contactId0, event.getContactId()); + eventWaiter.assertEquals(contactId0From1, event.getContactId()); responseReceived = true; eventWaiter.resume(); } } } - private void startLifecycles() throws InterruptedException { - // Start the lifecycle manager and wait for it to finish - lifecycleManager0 = t0.getLifecycleManager(); - lifecycleManager1 = t1.getLifecycleManager(); - lifecycleManager2 = t2.getLifecycleManager(); - lifecycleManager0.startServices(SHARER); - lifecycleManager1.startServices(INVITEE); - lifecycleManager2.startServices(SHARER2); - lifecycleManager0.waitForStartup(); - lifecycleManager1.waitForStartup(); - lifecycleManager2.waitForStartup(); - } - - private void stopLifecycles() throws InterruptedException { - // Clean up - lifecycleManager0.stopServices(); - lifecycleManager1.stopServices(); - lifecycleManager2.stopServices(); - lifecycleManager0.waitForShutdown(); - lifecycleManager1.waitForShutdown(); - lifecycleManager2.waitForShutdown(); - } - - private void defaultInit(boolean accept) throws DbException { - getDefaultIdentities(); - addDefaultContacts(); - addForumForSharer(); - listenToEvents(accept); - } - - private void getDefaultIdentities() throws DbException { - author0 = identityManager0.getLocalAuthor(); - author1 = identityManager1.getLocalAuthor(); - author2 = identityManager2.getLocalAuthor(); - } - - private void addDefaultContacts() throws DbException { - // sharer adds invitee as contact - contactId1 = contactManager0.addContact(author1, - author0.getId(), master, clock.currentTimeMillis(), true, - true, true - ); - // second sharer does the same - contactId21 = contactManager2.addContact(author1, - author2.getId(), master, clock.currentTimeMillis(), true, - true, true - ); - // invitee adds sharers back - contactId0 = contactManager1.addContact(author0, - author1.getId(), master, clock.currentTimeMillis(), true, - true, true - ); - contactId2 = contactManager1.addContact(author2, - author1.getId(), master, clock.currentTimeMillis(), true, - true, true - ); - } - - private void addForumForSharer() throws DbException { - // sharer creates forum - forum0 = forumManager0.addForum("Test Forum"); - } - - private void listenToEvents(boolean accept) { + private void listenToEvents(boolean accept) throws DbException { listener0 = new SharerListener(); - t0.getEventBus().addListener(listener0); + c0.getEventBus().addListener(listener0); listener1 = new InviteeListener(accept); - t1.getEventBus().addListener(listener1); + c1.getEventBus().addListener(listener1); listener2 = new SharerListener(); - t2.getEventBus().addListener(listener2); - } - - private void syncToInvitee() throws IOException, TimeoutException { - deliverMessage(sync0, contactId0, sync1, contactId1, 1, - "Sharer to Invitee"); - } - - private void syncToSharer() throws IOException, TimeoutException { - deliverMessage(sync1, contactId1, sync0, contactId0, 1, - "Invitee to Sharer"); - } - - private void deliverMessage(SyncSessionFactory fromSync, ContactId fromId, - SyncSessionFactory toSync, ContactId toId, int num, String debug) - throws IOException, TimeoutException { - - if (debug != null) LOG.info("TEST: Sending message from " + debug); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - // Create an outgoing sync session - SyncSession sessionFrom = - fromSync.createSimplexOutgoingSession(toId, MAX_LATENCY, out); - // Write whatever needs to be written - sessionFrom.run(); - out.close(); - - ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); - // Create an incoming sync session - SyncSession sessionTo = toSync.createIncomingSession(fromId, in); - // Read whatever needs to be read - sessionTo.run(); - in.close(); - - // wait for message to actually arrive - msgWaiter.await(TIMEOUT, num); - } - - private void injectEagerSingletons( - ForumSharingIntegrationTestComponent component) { - - component.inject(new LifecycleModule.EagerSingletons()); - component.inject(new ForumModule.EagerSingletons()); - component.inject(new CryptoModule.EagerSingletons()); - component.inject(new ContactModule.EagerSingletons()); - component.inject(new TransportModule.EagerSingletons()); - component.inject(new SharingModule.EagerSingletons()); - component.inject(new SyncModule.EagerSingletons()); - component.inject(new PropertiesModule.EagerSingletons()); + c2.getEventBus().addListener(listener2); } } diff --git a/briar-android-tests/src/test/java/org/briarproject/PrivateGroupManagerTest.java b/briar-android-tests/src/test/java/org/briarproject/PrivateGroupManagerTest.java index ab8fa52cc1bbc23b0ff5a70d52bdf6e3723c6195..4e1dbc0cd25b1296f1951b2480657f10add853ed 100644 --- a/briar-android-tests/src/test/java/org/briarproject/PrivateGroupManagerTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/PrivateGroupManagerTest.java @@ -1,65 +1,22 @@ package org.briarproject; -import net.jodah.concurrentunit.Waiter; - -import org.briarproject.api.clients.ClientHelper; -import org.briarproject.api.clients.ContactGroupFactory; import org.briarproject.api.clients.MessageTracker.GroupCount; import org.briarproject.api.contact.Contact; -import org.briarproject.api.contact.ContactId; -import org.briarproject.api.contact.ContactManager; -import org.briarproject.api.crypto.CryptoComponent; -import org.briarproject.api.crypto.KeyPair; -import org.briarproject.api.crypto.SecretKey; import org.briarproject.api.data.BdfList; -import org.briarproject.api.db.DatabaseComponent; -import org.briarproject.api.db.DbException; import org.briarproject.api.db.Transaction; -import org.briarproject.api.event.Event; -import org.briarproject.api.event.EventListener; -import org.briarproject.api.event.MessageStateChangedEvent; -import org.briarproject.api.identity.AuthorFactory; -import org.briarproject.api.identity.IdentityManager; -import org.briarproject.api.identity.LocalAuthor; -import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.privategroup.GroupMember; import org.briarproject.api.privategroup.GroupMessage; -import org.briarproject.api.privategroup.GroupMessageFactory; import org.briarproject.api.privategroup.GroupMessageHeader; import org.briarproject.api.privategroup.JoinMessageHeader; import org.briarproject.api.privategroup.PrivateGroup; -import org.briarproject.api.privategroup.PrivateGroupFactory; import org.briarproject.api.privategroup.PrivateGroupManager; -import org.briarproject.api.privategroup.invitation.GroupInvitationFactory; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.MessageId; -import org.briarproject.api.sync.SyncSession; -import org.briarproject.api.sync.SyncSessionFactory; -import org.briarproject.api.system.Clock; -import org.briarproject.contact.ContactModule; -import org.briarproject.crypto.CryptoModule; -import org.briarproject.lifecycle.LifecycleModule; -import org.briarproject.privategroup.PrivateGroupModule; -import org.briarproject.properties.PropertiesModule; -import org.briarproject.sync.SyncModule; -import org.briarproject.transport.TransportModule; -import org.junit.After; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.IOException; import java.util.Collection; -import java.util.concurrent.TimeoutException; -import java.util.logging.Logger; - -import javax.inject.Inject; -import static org.briarproject.TestPluginsModule.MAX_LATENCY; import static org.briarproject.TestUtils.getRandomBytes; import static org.briarproject.api.identity.Author.Status.VERIFIED; import static org.briarproject.api.privategroup.Visibility.INVISIBLE; @@ -68,110 +25,32 @@ import static org.briarproject.api.privategroup.Visibility.REVEALED_BY_US; import static org.briarproject.api.privategroup.Visibility.VISIBLE; import static org.briarproject.api.privategroup.invitation.GroupInvitationFactory.SIGNING_LABEL_INVITE; import static org.briarproject.api.sync.Group.Visibility.SHARED; -import static org.briarproject.api.sync.ValidationManager.State.DELIVERED; -import static org.briarproject.api.sync.ValidationManager.State.INVALID; -import static org.briarproject.api.sync.ValidationManager.State.PENDING; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class PrivateGroupManagerTest extends BriarIntegrationTest { - private LifecycleManager lifecycleManager0, lifecycleManager1, - lifecycleManager2; - private SyncSessionFactory sync0, sync1, sync2; - private PrivateGroupManager groupManager0, groupManager1, groupManager2; - private ContactManager contactManager0, contactManager1, contactManager2; - private ContactId contactId01, contactId02, contactId1, contactId2; - private IdentityManager identityManager0, identityManager1, - identityManager2; - private LocalAuthor author0, author1, author2; - private DatabaseComponent db0, db1, db2; private PrivateGroup privateGroup0; private GroupId groupId0; - - @Inject - Clock clock; - @Inject - AuthorFactory authorFactory; - @Inject - ClientHelper clientHelper; - @Inject - CryptoComponent crypto; - @Inject - ContactGroupFactory contactGroupFactory; - @Inject - PrivateGroupFactory privateGroupFactory; - @Inject - GroupMessageFactory groupMessageFactory; - @Inject - GroupInvitationFactory groupInvitationFactory; - - // objects accessed from background threads need to be volatile - private volatile Waiter validationWaiter; - private volatile Waiter deliveryWaiter; - - private final File testDir = TestUtils.getTestDirectory(); - private final SecretKey master = TestUtils.getSecretKey(); - private final int TIMEOUT = 15000; - private final String AUTHOR0 = "Author 0"; - private final String AUTHOR1 = "Author 1"; - private final String AUTHOR2 = "Author 2"; - - private static final Logger LOG = - Logger.getLogger(PrivateGroupManagerTest.class.getName()); - - private PrivateGroupManagerTestComponent t0, t1, t2; - - @Rule - public ExpectedException thrown = ExpectedException.none(); + private PrivateGroupManager groupManager0, groupManager1, groupManager2; @Before public void setUp() throws Exception { - PrivateGroupManagerTestComponent component = - DaggerPrivateGroupManagerTestComponent.builder().build(); - component.inject(this); - - assertTrue(testDir.mkdirs()); - File t0Dir = new File(testDir, AUTHOR0); - t0 = DaggerPrivateGroupManagerTestComponent.builder() - .testDatabaseModule(new TestDatabaseModule(t0Dir)).build(); - injectEagerSingletons(t0); - File t1Dir = new File(testDir, AUTHOR1); - t1 = DaggerPrivateGroupManagerTestComponent.builder() - .testDatabaseModule(new TestDatabaseModule(t1Dir)).build(); - injectEagerSingletons(t1); - File t2Dir = new File(testDir, AUTHOR2); - t2 = DaggerPrivateGroupManagerTestComponent.builder() - .testDatabaseModule(new TestDatabaseModule(t2Dir)).build(); - injectEagerSingletons(t2); - - identityManager0 = t0.getIdentityManager(); - identityManager1 = t1.getIdentityManager(); - identityManager2 = t2.getIdentityManager(); - contactManager0 = t0.getContactManager(); - contactManager1 = t1.getContactManager(); - contactManager2 = t2.getContactManager(); - db0 = t0.getDatabaseComponent(); - db1 = t1.getDatabaseComponent(); - db2 = t2.getDatabaseComponent(); - groupManager0 = t0.getPrivateGroupManager(); - groupManager1 = t1.getPrivateGroupManager(); - groupManager2 = t2.getPrivateGroupManager(); - sync0 = t0.getSyncSessionFactory(); - sync1 = t1.getSyncSessionFactory(); - sync2 = t2.getSyncSessionFactory(); - - // initialize waiters fresh for each test - validationWaiter = new Waiter(); - deliveryWaiter = new Waiter(); - - startLifecycles(); + super.setUp(); + + groupManager0 = c0.getPrivateGroupManager(); + groupManager1 = c1.getPrivateGroupManager(); + groupManager2 = c2.getPrivateGroupManager(); + + privateGroup0 = + privateGroupFactory.createPrivateGroup("Testgroup", author0); + groupId0 = privateGroup0.getId(); } @Test public void testSendingMessage() throws Exception { - defaultInit(); + addGroup(); // create and add test message long time = clock.currentTimeMillis(); @@ -186,8 +65,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { groupManager0.getPreviousMsgId(groupId0)); // sync test message - sync0To1(); - deliveryWaiter.await(TIMEOUT, 1); + sync0To1(1, true); // assert that message arrived as expected Collection<GroupMessageHeader> headers = @@ -213,7 +91,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { @Test public void testMessageWithWrongPreviousMsgId() throws Exception { - defaultInit(); + addGroup(); // create and add test message with no previousMsgId @SuppressWarnings("ConstantConditions") @@ -223,8 +101,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { groupManager0.addLocalMessage(msg); // sync test message - sync0To1(); - validationWaiter.await(TIMEOUT, 1); + sync0To1(1, false); // assert that message did not arrive assertEquals(2, groupManager1.getHeaders(groupId0).size()); @@ -237,8 +114,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { groupManager0.addLocalMessage(msg); // sync test message - sync0To1(); - validationWaiter.await(TIMEOUT, 1); + sync0To1(1, false); // assert that message did not arrive assertEquals(2, groupManager1.getHeaders(groupId0).size()); @@ -251,8 +127,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { groupManager0.addLocalMessage(msg); // sync test message - sync0To1(); - validationWaiter.await(TIMEOUT, 1); + sync0To1(1, false); // assert that message did not arrive assertEquals(2, groupManager1.getHeaders(groupId0).size()); @@ -260,7 +135,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { @Test public void testMessageWithWrongParentMsgId() throws Exception { - defaultInit(); + addGroup(); // create and add test message with random parentMsgId MessageId parentMsgId = new MessageId(TestUtils.getRandomId()); @@ -271,8 +146,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { groupManager0.addLocalMessage(msg); // sync test message - sync0To1(); - validationWaiter.await(TIMEOUT, 1); + sync0To1(1, false); // assert that message did not arrive assertEquals(2, groupManager1.getHeaders(groupId0).size()); @@ -285,8 +159,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { groupManager0.addLocalMessage(msg); // sync test message - sync0To1(); - validationWaiter.await(TIMEOUT, 1); + sync0To1(1, false); // assert that message did not arrive assertEquals(2, groupManager1.getHeaders(groupId0).size()); @@ -294,7 +167,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { @Test public void testMessageWithWrongTimestamp() throws Exception { - defaultInit(); + addGroup(); // create and add test message with wrong timestamp MessageId previousMsgId = groupManager0.getPreviousMsgId(groupId0); @@ -304,8 +177,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { groupManager0.addLocalMessage(msg); // sync test message - sync0To1(); - validationWaiter.await(TIMEOUT, 1); + sync0To1(1, false); // assert that message did not arrive assertEquals(2, groupManager1.getHeaders(groupId0).size()); @@ -318,8 +190,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { groupManager0.addLocalMessage(msg); // sync test message - sync0To1(); - deliveryWaiter.await(TIMEOUT, 1); + sync0To1(1, true); assertEquals(3, groupManager1.getHeaders(groupId0).size()); // create and add test message with same timestamp as previous message @@ -330,8 +201,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { groupManager0.addLocalMessage(msg); // sync test message - sync0To1(); - validationWaiter.await(TIMEOUT, 1); + sync0To1(1, false); // assert that message did not arrive assertEquals(3, groupManager1.getHeaders(groupId0).size()); @@ -339,10 +209,6 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { @Test public void testWrongJoinMessages1() throws Exception { - addDefaultIdentities(); - addDefaultContacts(); - listenToEvents(); - // author0 joins privateGroup0 with wrong join message long joinTime = clock.currentTimeMillis(); GroupMessage joinMsg0 = groupMessageFactory @@ -354,14 +220,14 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { // share the group with 1 Transaction txn0 = db0.startTransaction(false); - db0.setGroupVisibility(txn0, contactId1, privateGroup0.getId(), SHARED); + db0.setGroupVisibility(txn0, contactId1From0, privateGroup0.getId(), SHARED); db0.commitTransaction(txn0); db0.endTransaction(txn0); // author1 joins privateGroup0 with wrong timestamp joinTime = clock.currentTimeMillis(); long inviteTime = joinTime; - Contact c1 = contactManager0.getContact(contactId1); + Contact c1 = contactManager0.getContact(contactId1From0); byte[] creatorSignature = groupInvitationFactory .signInvitation(c1, privateGroup0.getId(), inviteTime, author0.getPrivateKey()); @@ -374,20 +240,18 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { // share the group with 0 Transaction txn1 = db1.startTransaction(false); - db1.setGroupVisibility(txn1, contactId01, privateGroup0.getId(), + db1.setGroupVisibility(txn1, contactId0From1, privateGroup0.getId(), SHARED); db1.commitTransaction(txn1); db1.endTransaction(txn1); // sync join messages - sync0To1(); - validationWaiter.await(TIMEOUT, 1); + sync0To1(1, false); // assert that 0 never joined the group from 1's perspective assertEquals(1, groupManager1.getHeaders(groupId0).size()); - sync1To0(); - validationWaiter.await(TIMEOUT, 1); + sync1To0(1, false); // assert that 1 never joined the group from 0's perspective assertEquals(1, groupManager0.getHeaders(groupId0).size()); @@ -395,10 +259,6 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { @Test public void testWrongJoinMessages2() throws Exception { - addDefaultIdentities(); - addDefaultContacts(); - listenToEvents(); - // author0 joins privateGroup0 with wrong member's join message long joinTime = clock.currentTimeMillis(); long inviteTime = joinTime - 1; @@ -417,7 +277,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { // share the group with 1 Transaction txn0 = db0.startTransaction(false); - db0.setGroupVisibility(txn0, contactId1, privateGroup0.getId(), SHARED); + db0.setGroupVisibility(txn0, contactId1From0, privateGroup0.getId(), SHARED); db0.commitTransaction(txn0); db0.endTransaction(txn0); @@ -425,7 +285,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { joinTime = clock.currentTimeMillis(); inviteTime = joinTime - 1; // signature uses joiner's key, not creator's key - Contact c1 = contactManager0.getContact(contactId1); + Contact c1 = contactManager0.getContact(contactId1From0); creatorSignature = groupInvitationFactory .signInvitation(c1, privateGroup0.getId(), inviteTime, author1.getPrivateKey()); @@ -438,19 +298,17 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { // share the group with 0 Transaction txn1 = db1.startTransaction(false); - db1.setGroupVisibility(txn1, contactId01, privateGroup0.getId(), SHARED); + db1.setGroupVisibility(txn1, contactId0From1, privateGroup0.getId(), SHARED); db1.commitTransaction(txn1); db1.endTransaction(txn1); // sync join messages - sync0To1(); - validationWaiter.await(TIMEOUT, 1); + sync0To1(1, false); // assert that 0 never joined the group from 1's perspective assertEquals(1, groupManager1.getHeaders(groupId0).size()); - sync1To0(); - validationWaiter.await(TIMEOUT, 1); + sync1To0(1, false); // assert that 1 never joined the group from 0's perspective assertEquals(1, groupManager0.getHeaders(groupId0).size()); @@ -458,7 +316,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { @Test public void testGetMembers() throws Exception { - defaultInit(); + addGroup(); Collection<GroupMember> members0 = groupManager0.getMembers(groupId0); assertEquals(2, members0.size()); @@ -485,7 +343,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { @Test public void testJoinMessages() throws Exception { - defaultInit(); + addGroup(); Collection<GroupMessageHeader> headers0 = groupManager0.getHeaders(groupId0); @@ -514,18 +372,18 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { @Test public void testRevealingRelationships() throws Exception { - defaultInit(); + addGroup(); // share the group with 2 Transaction txn0 = db0.startTransaction(false); - db0.setGroupVisibility(txn0, contactId2, privateGroup0.getId(), SHARED); + db0.setGroupVisibility(txn0, contactId2From0, privateGroup0.getId(), SHARED); db0.commitTransaction(txn0); db0.endTransaction(txn0); // author2 joins privateGroup0 long joinTime = clock.currentTimeMillis(); long inviteTime = joinTime - 1; - Contact c2 = contactManager0.getContact(contactId2); + Contact c2 = contactManager0.getContact(contactId2From0); byte[] creatorSignature = groupInvitationFactory .signInvitation(c2, privateGroup0.getId(), inviteTime, author0.getPrivateKey()); @@ -536,18 +394,15 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { groupManager2.addPrivateGroup(txn2, privateGroup0, joinMsg2, false); // share the group with 0 - db2.setGroupVisibility(txn2, contactId01, privateGroup0.getId(), + db2.setGroupVisibility(txn2, contactId0From1, privateGroup0.getId(), SHARED); db2.commitTransaction(txn2); db2.endTransaction(txn2); // sync join messages - deliverMessage(sync2, contactId2, sync0, contactId02, "2 to 0"); - deliveryWaiter.await(TIMEOUT, 1); - deliverMessage(sync0, contactId02, sync2, contactId2, "0 to 2"); - deliveryWaiter.await(TIMEOUT, 2); - sync0To1(); - deliveryWaiter.await(TIMEOUT, 1); + sync2To0(1, true); + sync0To2(2, true); + sync0To1(1, true); // check that everybody sees everybody else as joined Collection<GroupMember> members0 = groupManager0.getMembers(groupId0); @@ -626,7 +481,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { @Test public void testDissolveGroup() throws Exception { - defaultInit(); + addGroup(); // group is not dissolved initially assertFalse(groupManager1.isDissolved(groupId0)); @@ -641,93 +496,6 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { assertTrue(groupManager1.isDissolved(groupId0)); } - @After - public void tearDown() throws Exception { - stopLifecycles(); - TestUtils.deleteTestDirectory(testDir); - } - - private class Listener implements EventListener { - @Override - public void eventOccurred(Event e) { - if (e instanceof MessageStateChangedEvent) { - MessageStateChangedEvent event = (MessageStateChangedEvent) e; - if (!event.isLocal()) { - if (event.getState() == DELIVERED) { - LOG.info("Delivered new message"); - deliveryWaiter.resume(); - } else if (event.getState() == INVALID || - event.getState() == PENDING) { - LOG.info("Validated new " + event.getState().name() + - " message"); - validationWaiter.resume(); - } - } - } - } - } - - private void defaultInit() throws Exception { - addDefaultIdentities(); - addDefaultContacts(); - listenToEvents(); - addGroup(); - } - - private void addDefaultIdentities() throws DbException { - KeyPair keyPair0 = crypto.generateSignatureKeyPair(); - byte[] publicKey0 = keyPair0.getPublic().getEncoded(); - byte[] privateKey0 = keyPair0.getPrivate().getEncoded(); - author0 = authorFactory - .createLocalAuthor(AUTHOR0, publicKey0, privateKey0); - identityManager0.registerLocalAuthor(author0); - privateGroup0 = - privateGroupFactory.createPrivateGroup("Testgroup", author0); - groupId0 = privateGroup0.getId(); - - KeyPair keyPair1 = crypto.generateSignatureKeyPair(); - byte[] publicKey1 = keyPair1.getPublic().getEncoded(); - byte[] privateKey1 = keyPair1.getPrivate().getEncoded(); - author1 = authorFactory - .createLocalAuthor(AUTHOR1, publicKey1, privateKey1); - identityManager1.registerLocalAuthor(author1); - - KeyPair keyPair2 = crypto.generateSignatureKeyPair(); - byte[] publicKey2 = keyPair2.getPublic().getEncoded(); - byte[] privateKey2 = keyPair2.getPrivate().getEncoded(); - author2 = authorFactory - .createLocalAuthor(AUTHOR2, publicKey2, privateKey2); - identityManager2.registerLocalAuthor(author2); - } - - private void addDefaultContacts() throws DbException { - // creator adds invitee as contact - contactId1 = contactManager0 - .addContact(author1, author0.getId(), master, - clock.currentTimeMillis(), true, true, true); - // invitee adds creator back - contactId01 = contactManager1 - .addContact(author0, author1.getId(), master, - clock.currentTimeMillis(), true, true, true); - // creator adds invitee as contact - contactId2 = contactManager0 - .addContact(author2, author0.getId(), master, - clock.currentTimeMillis(), true, true, true); - // invitee adds creator back - contactId02 = contactManager2 - .addContact(author0, author2.getId(), master, - clock.currentTimeMillis(), true, true, true); - } - - private void listenToEvents() { - Listener listener0 = new Listener(); - t0.getEventBus().addListener(listener0); - Listener listener1 = new Listener(); - t1.getEventBus().addListener(listener1); - Listener listener2 = new Listener(); - t2.getEventBus().addListener(listener2); - } - private void addGroup() throws Exception { // author0 joins privateGroup0 long joinTime = clock.currentTimeMillis(); @@ -739,14 +507,14 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { // share the group with 1 Transaction txn0 = db0.startTransaction(false); - db0.setGroupVisibility(txn0, contactId1, privateGroup0.getId(), SHARED); + db0.setGroupVisibility(txn0, contactId1From0, privateGroup0.getId(), SHARED); db0.commitTransaction(txn0); db0.endTransaction(txn0); // author1 joins privateGroup0 joinTime = clock.currentTimeMillis(); long inviteTime = joinTime - 1; - Contact c1 = contactManager0.getContact(contactId1); + Contact c1 = contactManager0.getContact(contactId1From0); byte[] creatorSignature = groupInvitationFactory .signInvitation(c1, privateGroup0.getId(), inviteTime, author0.getPrivateKey()); @@ -757,7 +525,7 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { // share the group with 0 Transaction txn1 = db1.startTransaction(false); - db1.setGroupVisibility(txn1, contactId01, privateGroup0.getId(), + db1.setGroupVisibility(txn1, contactId0From1, privateGroup0.getId(), SHARED); db1.commitTransaction(txn1); db1.endTransaction(txn1); @@ -765,74 +533,8 @@ public class PrivateGroupManagerTest extends BriarIntegrationTest { groupManager1.getPreviousMsgId(groupId0)); // sync join messages - sync0To1(); - deliveryWaiter.await(TIMEOUT, 1); - sync1To0(); - deliveryWaiter.await(TIMEOUT, 1); - } - - private void sync0To1() throws IOException, TimeoutException { - deliverMessage(sync0, contactId01, sync1, contactId1, "0 to 1"); - } - - private void sync1To0() throws IOException, TimeoutException { - deliverMessage(sync1, contactId1, sync0, contactId01, "1 to 0"); - } - - private void deliverMessage(SyncSessionFactory fromSync, ContactId fromId, - SyncSessionFactory toSync, ContactId toId, String debug) - throws IOException, TimeoutException { - - if (debug != null) LOG.info("TEST: Sending message from " + debug); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - // Create an outgoing sync session - SyncSession sessionFrom = - fromSync.createSimplexOutgoingSession(toId, MAX_LATENCY, out); - // Write whatever needs to be written - sessionFrom.run(); - out.close(); - - ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); - // Create an incoming sync session - SyncSession sessionTo = toSync.createIncomingSession(fromId, in); - // Read whatever needs to be read - sessionTo.run(); - in.close(); - } - - private void startLifecycles() throws InterruptedException { - // Start the lifecycle manager and wait for it to finish - lifecycleManager0 = t0.getLifecycleManager(); - lifecycleManager1 = t1.getLifecycleManager(); - lifecycleManager2 = t2.getLifecycleManager(); - lifecycleManager0.startServices(AUTHOR0); - lifecycleManager1.startServices(AUTHOR1); - lifecycleManager2.startServices(AUTHOR2); - lifecycleManager0.waitForStartup(); - lifecycleManager1.waitForStartup(); - lifecycleManager2.waitForStartup(); - } - - private void stopLifecycles() throws InterruptedException { - // Clean up - lifecycleManager0.stopServices(); - lifecycleManager1.stopServices(); - lifecycleManager2.stopServices(); - lifecycleManager0.waitForShutdown(); - lifecycleManager1.waitForShutdown(); - lifecycleManager2.waitForShutdown(); - } - - private void injectEagerSingletons( - PrivateGroupManagerTestComponent component) { - component.inject(new LifecycleModule.EagerSingletons()); - component.inject(new PrivateGroupModule.EagerSingletons()); - component.inject(new CryptoModule.EagerSingletons()); - component.inject(new ContactModule.EagerSingletons()); - component.inject(new TransportModule.EagerSingletons()); - component.inject(new SyncModule.EagerSingletons()); - component.inject(new PropertiesModule.EagerSingletons()); + sync0To1(1, true); + sync1To0(1, true); } } diff --git a/briar-android-tests/src/test/java/org/briarproject/PrivateGroupManagerTestComponent.java b/briar-android-tests/src/test/java/org/briarproject/PrivateGroupManagerTestComponent.java deleted file mode 100644 index 08bdfd8a6b0dc1951a2a5ae0aacfa8ea46334fbc..0000000000000000000000000000000000000000 --- a/briar-android-tests/src/test/java/org/briarproject/PrivateGroupManagerTestComponent.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.briarproject; - -import org.briarproject.api.contact.ContactManager; -import org.briarproject.api.db.DatabaseComponent; -import org.briarproject.api.event.EventBus; -import org.briarproject.api.identity.IdentityManager; -import org.briarproject.api.lifecycle.LifecycleManager; -import org.briarproject.api.privategroup.PrivateGroupManager; -import org.briarproject.api.sync.SyncSessionFactory; -import org.briarproject.clients.ClientsModule; -import org.briarproject.contact.ContactModule; -import org.briarproject.crypto.CryptoModule; -import org.briarproject.data.DataModule; -import org.briarproject.db.DatabaseModule; -import org.briarproject.event.EventModule; -import org.briarproject.identity.IdentityModule; -import org.briarproject.lifecycle.LifecycleModule; -import org.briarproject.messaging.MessagingModule; -import org.briarproject.privategroup.PrivateGroupModule; -import org.briarproject.privategroup.invitation.GroupInvitationModule; -import org.briarproject.properties.PropertiesModule; -import org.briarproject.sharing.SharingModule; -import org.briarproject.sync.SyncModule; -import org.briarproject.system.SystemModule; -import org.briarproject.transport.TransportModule; - -import javax.inject.Singleton; - -import dagger.Component; - -@Singleton -@Component(modules = { - TestDatabaseModule.class, - TestPluginsModule.class, - TestSeedProviderModule.class, - ClientsModule.class, - ContactModule.class, - CryptoModule.class, - DataModule.class, - DatabaseModule.class, - EventModule.class, - MessagingModule.class, - PrivateGroupModule.class, - GroupInvitationModule.class, - IdentityModule.class, - LifecycleModule.class, - PropertiesModule.class, - SharingModule.class, - SyncModule.class, - SystemModule.class, - TransportModule.class -}) -interface PrivateGroupManagerTestComponent { - - void inject(PrivateGroupManagerTest testCase); - - void inject(ContactModule.EagerSingletons init); - - void inject(CryptoModule.EagerSingletons init); - - void inject(PrivateGroupModule.EagerSingletons init); - - void inject(LifecycleModule.EagerSingletons init); - - void inject(PropertiesModule.EagerSingletons init); - - void inject(SyncModule.EagerSingletons init); - - void inject(TransportModule.EagerSingletons init); - - LifecycleManager getLifecycleManager(); - - EventBus getEventBus(); - - IdentityManager getIdentityManager(); - - ContactManager getContactManager(); - - PrivateGroupManager getPrivateGroupManager(); - - SyncSessionFactory getSyncSessionFactory(); - - DatabaseComponent getDatabaseComponent(); - -} diff --git a/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java b/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java index 826524cc18ae7f9a0d86ca37befe6bd924827e5d..1fb7ef67380ba64f59e5aaf4f3f49d69a34ced94 100644 --- a/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java +++ b/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTest.java @@ -1,26 +1,19 @@ package org.briarproject.introduction; -import android.support.annotation.Nullable; - import net.jodah.concurrentunit.Waiter; import org.briarproject.BriarIntegrationTest; -import org.briarproject.TestDatabaseModule; import org.briarproject.TestUtils; import org.briarproject.api.FormatException; import org.briarproject.api.clients.ClientHelper; -import org.briarproject.api.clients.MessageTracker; import org.briarproject.api.clients.SessionId; import org.briarproject.api.contact.Contact; import org.briarproject.api.contact.ContactId; -import org.briarproject.api.contact.ContactManager; -import org.briarproject.api.crypto.CryptoComponent; import org.briarproject.api.crypto.KeyPair; import org.briarproject.api.crypto.SecretKey; import org.briarproject.api.data.BdfDictionary; import org.briarproject.api.data.BdfEntry; import org.briarproject.api.data.BdfList; -import org.briarproject.api.db.DatabaseComponent; import org.briarproject.api.db.DbException; import org.briarproject.api.db.Metadata; import org.briarproject.api.db.Transaction; @@ -30,37 +23,17 @@ import org.briarproject.api.event.IntroductionAbortedEvent; import org.briarproject.api.event.IntroductionRequestReceivedEvent; import org.briarproject.api.event.IntroductionResponseReceivedEvent; import org.briarproject.api.event.IntroductionSucceededEvent; -import org.briarproject.api.event.MessageStateChangedEvent; -import org.briarproject.api.identity.AuthorFactory; -import org.briarproject.api.identity.IdentityManager; -import org.briarproject.api.identity.LocalAuthor; import org.briarproject.api.introduction.IntroductionManager; import org.briarproject.api.introduction.IntroductionMessage; import org.briarproject.api.introduction.IntroductionRequest; -import org.briarproject.api.lifecycle.LifecycleManager; import org.briarproject.api.properties.TransportProperties; import org.briarproject.api.properties.TransportPropertyManager; import org.briarproject.api.sync.Group; import org.briarproject.api.sync.GroupId; import org.briarproject.api.sync.MessageId; -import org.briarproject.api.sync.SyncSession; -import org.briarproject.api.sync.SyncSessionFactory; -import org.briarproject.api.sync.ValidationManager.State; -import org.briarproject.api.system.Clock; -import org.briarproject.contact.ContactModule; -import org.briarproject.crypto.CryptoModule; -import org.briarproject.lifecycle.LifecycleModule; -import org.briarproject.properties.PropertiesModule; -import org.briarproject.sync.SyncModule; -import org.briarproject.system.SystemModule; -import org.briarproject.transport.TransportModule; -import org.junit.After; import org.junit.Before; import org.junit.Test; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; import java.io.IOException; import java.security.GeneralSecurityException; import java.util.ArrayList; @@ -72,10 +45,8 @@ import java.util.Map.Entry; import java.util.concurrent.TimeoutException; import java.util.logging.Logger; -import javax.inject.Inject; - -import static org.briarproject.TestPluginsModule.MAX_LATENCY; import static org.briarproject.TestPluginsModule.TRANSPORT_ID; +import static org.briarproject.TestUtils.assertGroupCount; import static org.briarproject.api.clients.MessageQueueManager.QUEUE_STATE_KEY; import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH; import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY; @@ -92,8 +63,6 @@ import static org.briarproject.api.introduction.IntroductionConstants.TRANSPORT; import static org.briarproject.api.introduction.IntroductionConstants.TYPE; import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUEST; import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE; -import static org.briarproject.api.sync.ValidationManager.State.DELIVERED; -import static org.briarproject.api.sync.ValidationManager.State.INVALID; import static org.briarproject.introduction.IntroduceeManager.SIGNING_LABEL_RESPONSE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -102,38 +71,12 @@ import static org.junit.Assert.fail; public class IntroductionIntegrationTest extends BriarIntegrationTest { - private LifecycleManager lifecycleManager0, lifecycleManager1, - lifecycleManager2; - private SyncSessionFactory sync0, sync1, sync2; - private ContactManager contactManager0, contactManager1, contactManager2; - private MessageTracker messageTracker0, messageTracker1, messageTracker2; - private ContactId contactId0, contactId1, contactId2; - private IdentityManager identityManager0, identityManager1, - identityManager2; - private LocalAuthor author0, author1, author2; - - @Inject - Clock clock; - @Inject - CryptoComponent crypto; - @Inject - AuthorFactory authorFactory; - @Inject - IntroductionGroupFactory introductionGroupFactory; - // objects accessed from background threads need to be volatile private volatile IntroductionManager introductionManager0; private volatile IntroductionManager introductionManager1; private volatile IntroductionManager introductionManager2; private volatile Waiter eventWaiter; - private volatile Waiter msgWaiter; - - private final File testDir = TestUtils.getTestDirectory(); - private final SecretKey master = TestUtils.getSecretKey(); - private final int TIMEOUT = 15000; - private final String INTRODUCER = "Introducer"; - private final String INTRODUCEE1 = "Introducee1"; - private final String INTRODUCEE2 = "Introducee2"; + private IntroducerListener listener0; private IntroduceeListener listener1; private IntroduceeListener listener2; @@ -141,361 +84,289 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest { private static final Logger LOG = Logger.getLogger(IntroductionIntegrationTest.class.getName()); - private IntroductionIntegrationTestComponent t0, t1, t2; - interface StateVisitor { boolean visit(BdfDictionary response); } @Before - public void setUp() { - IntroductionIntegrationTestComponent component = - DaggerIntroductionIntegrationTestComponent.builder().build(); - component.inject(this); - injectEagerSingletons(component); - - assertTrue(testDir.mkdirs()); - File t0Dir = new File(testDir, INTRODUCER); - t0 = DaggerIntroductionIntegrationTestComponent.builder() - .testDatabaseModule(new TestDatabaseModule(t0Dir)).build(); - injectEagerSingletons(t0); - File t1Dir = new File(testDir, INTRODUCEE1); - t1 = DaggerIntroductionIntegrationTestComponent.builder() - .testDatabaseModule(new TestDatabaseModule(t1Dir)).build(); - injectEagerSingletons(t1); - File t2Dir = new File(testDir, INTRODUCEE2); - t2 = DaggerIntroductionIntegrationTestComponent.builder() - .testDatabaseModule(new TestDatabaseModule(t2Dir)).build(); - injectEagerSingletons(t2); - - identityManager0 = t0.getIdentityManager(); - identityManager1 = t1.getIdentityManager(); - identityManager2 = t2.getIdentityManager(); - contactManager0 = t0.getContactManager(); - contactManager1 = t1.getContactManager(); - contactManager2 = t2.getContactManager(); - messageTracker0 = t0.getMessageTracker(); - messageTracker1 = t1.getMessageTracker(); - messageTracker2 = t2.getMessageTracker(); - introductionManager0 = t0.getIntroductionManager(); - introductionManager1 = t1.getIntroductionManager(); - introductionManager2 = t2.getIntroductionManager(); - sync0 = t0.getSyncSessionFactory(); - sync1 = t1.getSyncSessionFactory(); - sync2 = t2.getSyncSessionFactory(); - - // initialize waiters fresh for each test + @Override + public void setUp() throws Exception { + super.setUp(); + + introductionManager0 = c0.getIntroductionManager(); + introductionManager1 = c1.getIntroductionManager(); + introductionManager2 = c2.getIntroductionManager(); + + // initialize waiter fresh for each test eventWaiter = new Waiter(); - msgWaiter = new Waiter(); + + addTransportProperties(); } @Test public void testIntroductionSession() throws Exception { - startLifecycles(); - try { - getDefaultIdentities(); - addDefaultContacts(); - addListeners(true, true); - addTransportProperties(); - - // make introduction - long time = clock.currentTimeMillis(); - Contact introducee1 = contactManager0.getContact(contactId1); - Contact introducee2 = contactManager0.getContact(contactId2); - introductionManager0 - .makeIntroduction(introducee1, introducee2, "Hi!", time); - - // check that messages are tracked properly - Group g1 = introductionGroupFactory - .createIntroductionGroup(introducee1); - Group g2 = introductionGroupFactory - .createIntroductionGroup(introducee2); - assertGroupCount(messageTracker0, g1.getId(), 1, 0, time); - assertGroupCount(messageTracker0, g2.getId(), 1, 0, time); - - // sync first request message - deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1"); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener1.requestReceived); - assertGroupCount(messageTracker1, g1.getId(), 2, 1); - - // sync second request message - deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2"); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener2.requestReceived); - assertGroupCount(messageTracker2, g2.getId(), 2, 1); - - // sync first response - deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0"); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener0.response1Received); - assertGroupCount(messageTracker0, g1.getId(), 2, 1); - - // sync second response - deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0"); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener0.response2Received); - assertGroupCount(messageTracker0, g2.getId(), 2, 1); - - // sync forwarded responses to introducees - deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1"); - deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2"); - assertGroupCount(messageTracker1, g1.getId(), 2, 1); - assertGroupCount(messageTracker2, g2.getId(), 2, 1); - - // sync first ACK and its forward - deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0"); - deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2"); - - // sync second ACK and its forward - deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0"); - deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 2"); - - // wait for introduction to succeed - eventWaiter.await(TIMEOUT, 2); - assertTrue(listener1.succeeded); - assertTrue(listener2.succeeded); - - assertTrue(contactManager1 - .contactExists(author2.getId(), author1.getId())); - assertTrue(contactManager2 - .contactExists(author1.getId(), author2.getId())); - - // make sure that introduced contacts are not verified - for (Contact c : contactManager1.getActiveContacts()) { - if (c.getAuthor().equals(author2)) { - assertFalse(c.isVerified()); - } + addListeners(true, true); + + // make introduction + long time = clock.currentTimeMillis(); + Contact introducee1 = contact1From0; + Contact introducee2 = contact2From0; + introductionManager0 + .makeIntroduction(introducee1, introducee2, "Hi!", time); + + // check that messages are tracked properly + Group g1 = introductionGroupFactory + .createIntroductionGroup(introducee1); + Group g2 = introductionGroupFactory + .createIntroductionGroup(introducee2); + assertGroupCount(messageTracker0, g1.getId(), 1, 0, time); + assertGroupCount(messageTracker0, g2.getId(), 1, 0, time); + + // sync first request message + sync0To1(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener1.requestReceived); + assertGroupCount(messageTracker1, g1.getId(), 2, 1); + + // sync second request message + sync0To2(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener2.requestReceived); + assertGroupCount(messageTracker2, g2.getId(), 2, 1); + + // sync first response + sync1To0(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener0.response1Received); + assertGroupCount(messageTracker0, g1.getId(), 2, 1); + + // sync second response + sync2To0(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener0.response2Received); + assertGroupCount(messageTracker0, g2.getId(), 2, 1); + + // sync forwarded responses to introducees + sync0To1(1, true); + sync0To2(1, true); + assertGroupCount(messageTracker1, g1.getId(), 2, 1); + assertGroupCount(messageTracker2, g2.getId(), 2, 1); + + // sync first ACK and its forward + sync1To0(1, true); + sync0To2(1, true); + + // sync second ACK and its forward + sync2To0(1, true); + sync0To1(1, true); + + // wait for introduction to succeed + eventWaiter.await(TIMEOUT, 2); + assertTrue(listener1.succeeded); + assertTrue(listener2.succeeded); + + assertTrue(contactManager1 + .contactExists(author2.getId(), author1.getId())); + assertTrue(contactManager2 + .contactExists(author1.getId(), author2.getId())); + + // make sure that introduced contacts are not verified + for (Contact c : contactManager1.getActiveContacts()) { + if (c.getAuthor().equals(author2)) { + assertFalse(c.isVerified()); } - for (Contact c : contactManager2.getActiveContacts()) { - if (c.getAuthor().equals(author1)) { - assertFalse(c.isVerified()); - } + } + for (Contact c : contactManager2.getActiveContacts()) { + if (c.getAuthor().equals(author1)) { + assertFalse(c.isVerified()); } - - assertDefaultUiMessages(); - assertGroupCount(messageTracker0, g1.getId(), 2, 1); - assertGroupCount(messageTracker0, g2.getId(), 2, 1); - assertGroupCount(messageTracker1, g1.getId(), 2, 1); - assertGroupCount(messageTracker2, g2.getId(), 2, 1); - } finally { - stopLifecycles(); } + + assertDefaultUiMessages(); + assertGroupCount(messageTracker0, g1.getId(), 2, 1); + assertGroupCount(messageTracker0, g2.getId(), 2, 1); + assertGroupCount(messageTracker1, g1.getId(), 2, 1); + assertGroupCount(messageTracker2, g2.getId(), 2, 1); } @Test public void testIntroductionSessionFirstDecline() throws Exception { - startLifecycles(); - try { - getDefaultIdentities(); - addDefaultContacts(); - addListeners(false, true); - addTransportProperties(); - - // make introduction - long time = clock.currentTimeMillis(); - Contact introducee1 = contactManager0.getContact(contactId1); - Contact introducee2 = contactManager0.getContact(contactId2); - introductionManager0 - .makeIntroduction(introducee1, introducee2, null, time); - - // sync request messages - deliverMessage(sync0, contactId0, sync1, contactId1); - deliverMessage(sync0, contactId0, sync2, contactId2); - - // wait for requests to arrive - eventWaiter.await(TIMEOUT, 2); - assertTrue(listener1.requestReceived); - assertTrue(listener2.requestReceived); - - // sync first response - deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0"); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener0.response1Received); - - // sync second response - deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0"); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener0.response2Received); - - // sync first forwarded response - deliverMessage(sync0, contactId0, sync2, contactId2); - - // note how the introducer does not forward the second response, - // because after the first decline the protocol finished - - assertFalse(listener1.succeeded); - assertFalse(listener2.succeeded); - - assertFalse(contactManager1 - .contactExists(author2.getId(), author1.getId())); - assertFalse(contactManager2 - .contactExists(author1.getId(), author2.getId())); - - Group g1 = introductionGroupFactory - .createIntroductionGroup(introducee1); - Group g2 = introductionGroupFactory - .createIntroductionGroup(introducee2); - assertEquals(2, - introductionManager0.getIntroductionMessages(contactId1) - .size()); - assertGroupCount(messageTracker0, g1.getId(), 2, 1); - assertEquals(2, - introductionManager0.getIntroductionMessages(contactId2) - .size()); - assertGroupCount(messageTracker0, g2.getId(), 2, 1); - assertEquals(2, - introductionManager1.getIntroductionMessages(contactId0) - .size()); - assertGroupCount(messageTracker1, g1.getId(), 2, 1); - // introducee2 should also have the decline response of introducee1 - assertEquals(3, - introductionManager2.getIntroductionMessages(contactId0) - .size()); - assertGroupCount(messageTracker2, g2.getId(), 3, 2); - } finally { - stopLifecycles(); - } + addListeners(false, true); + + // make introduction + long time = clock.currentTimeMillis(); + Contact introducee1 = contact1From0; + Contact introducee2 = contact2From0; + introductionManager0 + .makeIntroduction(introducee1, introducee2, null, time); + + // sync request messages + sync0To1(1, true); + sync0To2(1, true); + + // wait for requests to arrive + eventWaiter.await(TIMEOUT, 2); + assertTrue(listener1.requestReceived); + assertTrue(listener2.requestReceived); + + // sync first response + sync1To0(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener0.response1Received); + + // sync second response + sync2To0(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener0.response2Received); + + // sync first forwarded response + sync0To2(1, true); + + // note how the introducer does not forward the second response, + // because after the first decline the protocol finished + + assertFalse(listener1.succeeded); + assertFalse(listener2.succeeded); + + assertFalse(contactManager1 + .contactExists(author2.getId(), author1.getId())); + assertFalse(contactManager2 + .contactExists(author1.getId(), author2.getId())); + + Group g1 = introductionGroupFactory + .createIntroductionGroup(introducee1); + Group g2 = introductionGroupFactory + .createIntroductionGroup(introducee2); + assertEquals(2, + introductionManager0.getIntroductionMessages(contactId1From0) + .size()); + assertGroupCount(messageTracker0, g1.getId(), 2, 1); + assertEquals(2, + introductionManager0.getIntroductionMessages(contactId2From0) + .size()); + assertGroupCount(messageTracker0, g2.getId(), 2, 1); + assertEquals(2, + introductionManager1.getIntroductionMessages(contactId0From1) + .size()); + assertGroupCount(messageTracker1, g1.getId(), 2, 1); + // introducee2 should also have the decline response of introducee1 + assertEquals(3, + introductionManager2.getIntroductionMessages(contactId0From2) + .size()); + assertGroupCount(messageTracker2, g2.getId(), 3, 2); } @Test public void testIntroductionSessionSecondDecline() throws Exception { - startLifecycles(); - try { - getDefaultIdentities(); - addDefaultContacts(); - addListeners(true, false); - addTransportProperties(); - - // make introduction - long time = clock.currentTimeMillis(); - Contact introducee1 = contactManager0.getContact(contactId1); - Contact introducee2 = contactManager0.getContact(contactId2); - introductionManager0 - .makeIntroduction(introducee1, introducee2, null, time); - - // sync request messages - deliverMessage(sync0, contactId0, sync1, contactId1); - deliverMessage(sync0, contactId0, sync2, contactId2); - - // wait for requests to arrive - eventWaiter.await(TIMEOUT, 2); - assertTrue(listener1.requestReceived); - assertTrue(listener2.requestReceived); - - // sync first response - deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0"); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener0.response1Received); - - // sync second response - deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0"); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener0.response2Received); - - // sync both forwarded response - deliverMessage(sync0, contactId0, sync2, contactId2); - deliverMessage(sync0, contactId0, sync1, contactId1); - - assertFalse(contactManager1 - .contactExists(author2.getId(), author1.getId())); - assertFalse(contactManager2 - .contactExists(author1.getId(), author2.getId())); - - assertEquals(2, - introductionManager0.getIntroductionMessages(contactId1) - .size()); - assertEquals(2, - introductionManager0.getIntroductionMessages(contactId2) - .size()); - // introducee1 also sees the decline response from introducee2 - assertEquals(3, - introductionManager1.getIntroductionMessages(contactId0) - .size()); - assertEquals(2, - introductionManager2.getIntroductionMessages(contactId0) - .size()); - } finally { - stopLifecycles(); - } + addListeners(true, false); + + // make introduction + long time = clock.currentTimeMillis(); + introductionManager0 + .makeIntroduction(contact1From0, contact2From0, null, time); + + // sync request messages + sync0To1(1, true); + sync0To2(1, true); + + // wait for requests to arrive + eventWaiter.await(TIMEOUT, 2); + assertTrue(listener1.requestReceived); + assertTrue(listener2.requestReceived); + + // sync first response + sync1To0(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener0.response1Received); + + // sync second response + sync2To0(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener0.response2Received); + + // sync both forwarded response + sync0To2(1, true); + sync0To1(1, true); + + assertFalse(contactManager1 + .contactExists(author2.getId(), author1.getId())); + assertFalse(contactManager2 + .contactExists(author1.getId(), author2.getId())); + + assertEquals(2, + introductionManager0.getIntroductionMessages(contactId1From0) + .size()); + assertEquals(2, + introductionManager0.getIntroductionMessages(contactId2From0) + .size()); + // introducee1 also sees the decline response from introducee2 + assertEquals(3, + introductionManager1.getIntroductionMessages(contactId0From1) + .size()); + assertEquals(2, + introductionManager2.getIntroductionMessages(contactId0From2) + .size()); } @Test public void testIntroductionSessionDelayedFirstDecline() throws Exception { - startLifecycles(); - try { - getDefaultIdentities(); - addDefaultContacts(); - addListeners(false, false); - addTransportProperties(); - - // make introduction - long time = clock.currentTimeMillis(); - Contact introducee1 = contactManager0.getContact(contactId1); - Contact introducee2 = contactManager0.getContact(contactId2); - introductionManager0 - .makeIntroduction(introducee1, introducee2, null, time); - - // sync request messages - deliverMessage(sync0, contactId0, sync1, contactId1); - deliverMessage(sync0, contactId0, sync2, contactId2); - - // wait for requests to arrive - eventWaiter.await(TIMEOUT, 2); - assertTrue(listener1.requestReceived); - assertTrue(listener2.requestReceived); - - // sync first response - deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0"); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener0.response1Received); - - // sync second response - deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0"); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener0.response2Received); - - // sync first forwarded response - deliverMessage(sync0, contactId0, sync2, contactId2); - - // note how the second response will not be forwarded anymore - - assertFalse(contactManager1 - .contactExists(author2.getId(), author1.getId())); - assertFalse(contactManager2 - .contactExists(author1.getId(), author2.getId())); - - // since introducee2 was already in FINISHED state when - // introducee1's response arrived, she ignores and deletes it - assertDefaultUiMessages(); - } finally { - stopLifecycles(); - } + addListeners(false, false); + + // make introduction + long time = clock.currentTimeMillis(); + introductionManager0 + .makeIntroduction(contact1From0, contact2From0, null, time); + + // sync request messages + sync0To1(1, true); + sync0To2(1, true); + + // wait for requests to arrive + eventWaiter.await(TIMEOUT, 2); + assertTrue(listener1.requestReceived); + assertTrue(listener2.requestReceived); + + // sync first response + sync1To0(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener0.response1Received); + + // sync second response + sync2To0(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener0.response2Received); + + // sync first forwarded response + sync0To2(1, true); + + // note how the second response will not be forwarded anymore + + assertFalse(contactManager1 + .contactExists(author2.getId(), author1.getId())); + assertFalse(contactManager2 + .contactExists(author1.getId(), author2.getId())); + + // since introducee2 was already in FINISHED state when + // introducee1's response arrived, she ignores and deletes it + assertDefaultUiMessages(); } @Test public void testResponseAndAckInOneSession() throws Exception { - startLifecycles(); - - getDefaultIdentities(); - addDefaultContacts(); addListeners(true, true); - addTransportProperties(); // make introduction long time = clock.currentTimeMillis(); - Contact introducee1 = contactManager0.getContact(contactId1); - Contact introducee2 = contactManager0.getContact(contactId2); introductionManager0 - .makeIntroduction(introducee1, introducee2, "Hi!", time); + .makeIntroduction(contact1From0, contact2From0, "Hi!", time); // sync first request message - deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1"); + sync0To1(1, true); eventWaiter.await(TIMEOUT, 1); assertTrue(listener1.requestReceived); // sync first response - deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0"); + sync1To0(1, true); eventWaiter.await(TIMEOUT, 1); assertTrue(listener0.response1Received); @@ -504,355 +375,293 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest { listener2.answerRequests = false; // sync second request message and first response - deliverMessage(sync0, contactId0, sync2, contactId2, 2, "0 to 2"); + sync0To2(2, true); eventWaiter.await(TIMEOUT, 1); assertTrue(listener2.requestReceived); // answer request manually introductionManager2 - .acceptIntroduction(contactId0, listener2.sessionId, time); + .acceptIntroduction(contactId0From2, listener2.sessionId, time); // sync second response and ACK and make sure there is no abort - deliverMessage(sync2, contactId2, sync0, contactId0, 2, "2 to 0"); + sync2To0(2, true); eventWaiter.await(TIMEOUT, 1); assertTrue(listener0.response2Received); assertFalse(listener0.aborted); - - stopLifecycles(); } @Test public void testIntroductionToSameContact() throws Exception { - startLifecycles(); - try { - getDefaultIdentities(); - addDefaultContacts(); - addListeners(true, false); - addTransportProperties(); - - // make introduction - long time = clock.currentTimeMillis(); - Contact introducee1 = contactManager0.getContact(contactId1); - introductionManager0 - .makeIntroduction(introducee1, introducee1, null, time); - - // sync request messages - deliverMessage(sync0, contactId0, sync1, contactId1); - - // we should not get any event, because the request will be discarded - assertFalse(listener1.requestReceived); - - // make really sure we don't have that request - assertTrue(introductionManager1.getIntroductionMessages(contactId0) - .isEmpty()); - } finally { - stopLifecycles(); - } + addListeners(true, false); + + // make introduction + long time = clock.currentTimeMillis(); + introductionManager0 + .makeIntroduction(contact1From0, contact1From0, null, time); + + // sync request messages + sync0To1(1, false); + + // we should not get any event, because the request will be discarded + assertFalse(listener1.requestReceived); + + // make really sure we don't have that request + assertTrue(introductionManager1.getIntroductionMessages(contactId0From1) + .isEmpty()); } @Test public void testSessionIdReuse() throws Exception { - startLifecycles(); - try { - getDefaultIdentities(); - addDefaultContacts(); - addListeners(true, true); - addTransportProperties(); - - // make introduction - long time = clock.currentTimeMillis(); - Contact introducee1 = contactManager0.getContact(contactId1); - Contact introducee2 = contactManager0.getContact(contactId2); - introductionManager0 - .makeIntroduction(introducee1, introducee2, "Hi!", time); - - // sync first request message - deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1"); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener1.requestReceived); - - // get SessionId - List<IntroductionMessage> list = new ArrayList<>( - introductionManager1.getIntroductionMessages(contactId0)); - assertEquals(2, list.size()); - assertTrue(list.get(0) instanceof IntroductionRequest); - IntroductionRequest msg = (IntroductionRequest) list.get(0); - SessionId sessionId = msg.getSessionId(); - - // get contact group - IntroductionGroupFactory groupFactory = - t0.getIntroductionGroupFactory(); - Group group = groupFactory.createIntroductionGroup(introducee1); - - // create new message with same SessionId - BdfDictionary d = BdfDictionary.of( - new BdfEntry(TYPE, TYPE_REQUEST), - new BdfEntry(SESSION_ID, sessionId), - new BdfEntry(GROUP_ID, group.getId()), - new BdfEntry(NAME, TestUtils.getRandomString(42)), - new BdfEntry(PUBLIC_KEY, - TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH)) - ); - - // reset request received state - listener1.requestReceived = false; - - // add the message to the queue - DatabaseComponent db0 = t0.getDatabaseComponent(); - MessageSender sender0 = t0.getMessageSender(); - Transaction txn = db0.startTransaction(false); - try { - sender0.sendMessage(txn, d); - db0.commitTransaction(txn); - } finally { - db0.endTransaction(txn); - } + addListeners(true, true); - // actually send message - deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1"); + // make introduction + long time = clock.currentTimeMillis(); + introductionManager0 + .makeIntroduction(contact1From0, contact2From0, "Hi!", time); - // make sure it does not arrive - assertFalse(listener1.requestReceived); + // sync first request message + sync0To1(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener1.requestReceived); + + // get SessionId + List<IntroductionMessage> list = new ArrayList<>( + introductionManager1.getIntroductionMessages(contactId0From1)); + assertEquals(2, list.size()); + assertTrue(list.get(0) instanceof IntroductionRequest); + IntroductionRequest msg = (IntroductionRequest) list.get(0); + SessionId sessionId = msg.getSessionId(); + + // get contact group + Group group = + introductionGroupFactory.createIntroductionGroup(contact1From0); + + // create new message with same SessionId + BdfDictionary d = BdfDictionary.of( + new BdfEntry(TYPE, TYPE_REQUEST), + new BdfEntry(SESSION_ID, sessionId), + new BdfEntry(GROUP_ID, group.getId()), + new BdfEntry(NAME, TestUtils.getRandomString(42)), + new BdfEntry(PUBLIC_KEY, + TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH)) + ); + + // reset request received state + listener1.requestReceived = false; + + // add the message to the queue + MessageSender sender0 = c0.getMessageSender(); + Transaction txn = db0.startTransaction(false); + try { + sender0.sendMessage(txn, d); + db0.commitTransaction(txn); } finally { - stopLifecycles(); + db0.endTransaction(txn); } + + // actually send message + sync0To1(1, false); + + // make sure it does not arrive + assertFalse(listener1.requestReceived); } @Test public void testIntroducerRemovedCleanup() throws Exception { - startLifecycles(); + addListeners(true, true); + + // make introduction + long time = clock.currentTimeMillis(); + introductionManager0 + .makeIntroduction(contact1From0, contact2From0, "Hi!", time); + + // sync first request message + sync0To1(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener1.requestReceived); + + // get database and local group for introducee + Group group1 = introductionGroupFactory.createLocalGroup(); + + // get local session state messages + Map<MessageId, Metadata> map; + Transaction txn = db1.startTransaction(false); try { - getDefaultIdentities(); - addDefaultContacts(); - addListeners(true, true); - addTransportProperties(); - - // make introduction - long time = clock.currentTimeMillis(); - Contact introducee1 = contactManager0.getContact(contactId1); - Contact introducee2 = contactManager0.getContact(contactId2); - introductionManager0 - .makeIntroduction(introducee1, introducee2, "Hi!", time); - - // sync first request message - deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1"); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener1.requestReceived); - - // get database and local group for introducee - DatabaseComponent db1 = t1.getDatabaseComponent(); - IntroductionGroupFactory groupFactory1 = - t1.getIntroductionGroupFactory(); - Group group1 = groupFactory1.createLocalGroup(); - - // get local session state messages - Map<MessageId, Metadata> map; - Transaction txn = db1.startTransaction(false); - try { - map = db1.getMessageMetadata(txn, group1.getId()); - db1.commitTransaction(txn); - } finally { - db1.endTransaction(txn); - } - // check that we have one session state - assertEquals(1, map.size()); + map = db1.getMessageMetadata(txn, group1.getId()); + db1.commitTransaction(txn); + } finally { + db1.endTransaction(txn); + } + // check that we have one session state + assertEquals(1, map.size()); - // introducee1 removes introducer - contactManager1.removeContact(contactId0); + // introducee1 removes introducer + contactManager1.removeContact(contactId0From1); - // get local session state messages again - txn = db1.startTransaction(false); - try { - map = db1.getMessageMetadata(txn, group1.getId()); - db1.commitTransaction(txn); - } finally { - db1.endTransaction(txn); - } - // make sure local state got deleted - assertEquals(0, map.size()); + // get local session state messages again + txn = db1.startTransaction(false); + try { + map = db1.getMessageMetadata(txn, group1.getId()); + db1.commitTransaction(txn); } finally { - stopLifecycles(); + db1.endTransaction(txn); } + // make sure local state got deleted + assertEquals(0, map.size()); } @Test public void testIntroduceesRemovedCleanup() throws Exception { - startLifecycles(); + addListeners(true, true); + + // make introduction + long time = clock.currentTimeMillis(); + introductionManager0 + .makeIntroduction(contact1From0, contact2From0, "Hi!", time); + + // sync first request message + sync0To1(1, true); + eventWaiter.await(TIMEOUT, 1); + assertTrue(listener1.requestReceived); + + // get database and local group for introducee + Group group1 = introductionGroupFactory.createLocalGroup(); + + // get local session state messages + Map<MessageId, Metadata> map; + Transaction txn = db0.startTransaction(false); try { - getDefaultIdentities(); - addDefaultContacts(); - addListeners(true, true); - addTransportProperties(); - - // make introduction - long time = clock.currentTimeMillis(); - Contact introducee1 = contactManager0.getContact(contactId1); - Contact introducee2 = contactManager0.getContact(contactId2); - introductionManager0 - .makeIntroduction(introducee1, introducee2, "Hi!", time); - - // sync first request message - deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1"); - eventWaiter.await(TIMEOUT, 1); - assertTrue(listener1.requestReceived); - - // get database and local group for introducee - DatabaseComponent db0 = t0.getDatabaseComponent(); - IntroductionGroupFactory groupFactory0 = - t0.getIntroductionGroupFactory(); - Group group1 = groupFactory0.createLocalGroup(); - - // get local session state messages - Map<MessageId, Metadata> map; - Transaction txn = db0.startTransaction(false); - try { - map = db0.getMessageMetadata(txn, group1.getId()); - db0.commitTransaction(txn); - } finally { - db0.endTransaction(txn); - } - // check that we have one session state - assertEquals(1, map.size()); + map = db0.getMessageMetadata(txn, group1.getId()); + db0.commitTransaction(txn); + } finally { + db0.endTransaction(txn); + } + // check that we have one session state + assertEquals(1, map.size()); - // introducer removes introducee1 - contactManager0.removeContact(contactId1); + // introducer removes introducee1 + contactManager0.removeContact(contactId1From0); - // get local session state messages again - txn = db0.startTransaction(false); - try { - map = db0.getMessageMetadata(txn, group1.getId()); - db0.commitTransaction(txn); - } finally { - db0.endTransaction(txn); - } - // make sure local state is still there - assertEquals(1, map.size()); + // get local session state messages again + txn = db0.startTransaction(false); + try { + map = db0.getMessageMetadata(txn, group1.getId()); + db0.commitTransaction(txn); + } finally { + db0.endTransaction(txn); + } + // make sure local state is still there + assertEquals(1, map.size()); - // introducer removes other introducee - contactManager0.removeContact(contactId2); + // introducer removes other introducee + contactManager0.removeContact(contactId2From0); - // get local session state messages again - txn = db0.startTransaction(false); - try { - map = db0.getMessageMetadata(txn, group1.getId()); - db0.commitTransaction(txn); - } finally { - db0.endTransaction(txn); - } - // make sure local state is gone now - assertEquals(0, map.size()); + // get local session state messages again + txn = db0.startTransaction(false); + try { + map = db0.getMessageMetadata(txn, group1.getId()); + db0.commitTransaction(txn); } finally { - stopLifecycles(); + db0.endTransaction(txn); } + // make sure local state is gone now + assertEquals(0, map.size()); } private void testModifiedResponse(StateVisitor visitor) throws Exception { - startLifecycles(); + addListeners(true, true); + + // make introduction + long time = clock.currentTimeMillis(); + introductionManager0 + .makeIntroduction(contact1From0, contact2From0, "Hi!", time); + + // sync request messages + sync0To1(1, true); + sync0To2(1, true); + eventWaiter.await(TIMEOUT, 2); + + // sync first response + sync1To0(1, true); + eventWaiter.await(TIMEOUT, 1); + + // get response to be forwarded + ClientHelper ch = c0.getClientHelper(); // need 0's ClientHelper here + Entry<MessageId, BdfDictionary> resp = + getMessageFor(ch, contact2From0, TYPE_RESPONSE); + MessageId responseId = resp.getKey(); + BdfDictionary response = resp.getValue(); + + // adapt outgoing message queue to removed message + Group g2 = introductionGroupFactory + .createIntroductionGroup(contact2From0); + decreaseOutgoingMessageCounter(ch, g2.getId(), 1); + + // allow visitor to modify response + boolean earlyAbort = visitor.visit(response); + + // replace original response with modified one + MessageSender sender0 = c0.getMessageSender(); + Transaction txn = db0.startTransaction(false); try { - getDefaultIdentities(); - addDefaultContacts(); - addListeners(true, true); - addTransportProperties(); - - // make introduction - long time = clock.currentTimeMillis(); - Contact introducee1 = contactManager0.getContact(contactId1); - Contact introducee2 = contactManager0.getContact(contactId2); - introductionManager0 - .makeIntroduction(introducee1, introducee2, "Hi!", time); - - // sync request messages - deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1"); - deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2"); - eventWaiter.await(TIMEOUT, 2); - - // sync first response - deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0"); - eventWaiter.await(TIMEOUT, 1); - - // get response to be forwarded - Entry<MessageId, BdfDictionary> resp = - getMessageFor(introducee2, TYPE_RESPONSE); - MessageId responseId = resp.getKey(); - BdfDictionary response = resp.getValue(); - - // adapt outgoing message queue to removed message - ClientHelper clientHelper0 = t0.getClientHelper(); - Group g2 = introductionGroupFactory - .createIntroductionGroup(introducee2); - decreaseOutgoingMessageCounter(clientHelper0, g2.getId(), 1); - - // allow visitor to modify response - boolean earlyAbort = visitor.visit(response); - - // replace original response with modified one - MessageSender sender0 = t0.getMessageSender(); - DatabaseComponent db0 = t0.getDatabaseComponent(); - Transaction txn = db0.startTransaction(false); - try { - db0.deleteMessage(txn, responseId); - sender0.sendMessage(txn, response); - db0.commitTransaction(txn); - } finally { - db0.endTransaction(txn); - } + db0.deleteMessage(txn, responseId); + sender0.sendMessage(txn, response); + db0.commitTransaction(txn); + } finally { + db0.endTransaction(txn); + } - // sync second response - deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0"); - eventWaiter.await(TIMEOUT, 1); + // sync second response + sync2To0(1, true); + eventWaiter.await(TIMEOUT, 1); - // sync forwarded responses to introducees - deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1"); - deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2"); + // sync forwarded responses to introducees + sync0To1(1, true); + sync0To2(1, true); - // sync first ACK and forward it - deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0"); - deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2"); + // sync first ACK and forward it + sync1To0(1, true); + sync0To2(1, true); - // introducee2 should have detected the fake now - // and deleted introducee1 again - Collection<Contact> contacts2; - DatabaseComponent db2 = t2.getDatabaseComponent(); - txn = db2.startTransaction(true); + // introducee2 should have detected the fake now + // and deleted introducee1 again + Collection<Contact> contacts2; + txn = db2.startTransaction(true); + try { + contacts2 = db2.getContacts(txn); + db2.commitTransaction(txn); + } finally { + db2.endTransaction(txn); + } + assertEquals(1, contacts2.size()); + + // sync introducee2's ack and following abort + sync2To0(2, true); + + // ensure introducer got the abort + assertTrue(listener0.aborted); + + // sync abort messages to introducees + sync0To1(2, true); + sync0To2(1, true); + + if (earlyAbort) { + assertTrue(listener1.aborted); + assertTrue(listener2.aborted); + } else { + assertTrue(listener2.aborted); + // when aborted late, introducee1 keeps the contact, + // so introducer can not make contacts disappear by aborting + Collection<Contact> contacts1; + txn = db1.startTransaction(true); try { - contacts2 = db2.getContacts(txn); - db2.commitTransaction(txn); + contacts1 = db1.getContacts(txn); + db1.commitTransaction(txn); } finally { - db2.endTransaction(txn); - } - assertEquals(1, contacts2.size()); - - // sync introducee2's ack and following abort - deliverMessage(sync2, contactId2, sync0, contactId0, 2, "2 to 0"); - - // ensure introducer got the abort - assertTrue(listener0.aborted); - - // sync abort messages to introducees - deliverMessage(sync0, contactId0, sync1, contactId1, 2, "0 to 1"); - deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2"); - - if (earlyAbort) { - assertTrue(listener1.aborted); - assertTrue(listener2.aborted); - } else { - assertTrue(listener2.aborted); - // when aborted late, introducee1 keeps the contact, - // so introducer can not make contacts disappear by aborting - Collection<Contact> contacts1; - DatabaseComponent db1 = t1.getDatabaseComponent(); - txn = db1.startTransaction(true); - try { - contacts1 = db1.getContacts(txn); - db1.commitTransaction(txn); - } finally { - db1.endTransaction(txn); - } - assertEquals(2, contacts1.size()); + db1.endTransaction(txn); } - } finally { - stopLifecycles(); + assertEquals(2, contacts1.size()); } } @@ -898,16 +707,12 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest { public void testModifiedEphemeralPublicKeyWithFakeMac() throws Exception { // initialize a real introducee manager - MessageSender messageSender = t2.getMessageSender(); - DatabaseComponent db = t2.getDatabaseComponent(); - ClientHelper clientHelper = t2.getClientHelper(); - TransportPropertyManager tpManager = t2.getTransportPropertyManager(); - ContactManager contactManager = t2.getContactManager(); - IdentityManager identityManager = t2.getIdentityManager(); + MessageSender messageSender = c2.getMessageSender(); + TransportPropertyManager tpManager = c2.getTransportPropertyManager(); IntroduceeManager manager2 = - new IntroduceeManager(messageSender, db, clientHelper, clock, - crypto, tpManager, authorFactory, contactManager, - identityManager, introductionGroupFactory); + new IntroduceeManager(messageSender, db2, clientHelper, clock, + crypto, tpManager, authorFactory, contactManager2, + identityManager2, introductionGroupFactory); // create keys KeyPair keyPair1 = crypto.generateSignatureKeyPair(); @@ -977,144 +782,49 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest { try { manager2.verifySignature(state); fail(); - } catch(GeneralSecurityException e) { + } catch (GeneralSecurityException e) { // expected } } - @After - public void tearDown() throws InterruptedException { - TestUtils.deleteTestDirectory(testDir); - } - - private void startLifecycles() throws InterruptedException { - // Start the lifecycle manager and wait for it to finish - lifecycleManager0 = t0.getLifecycleManager(); - lifecycleManager1 = t1.getLifecycleManager(); - lifecycleManager2 = t2.getLifecycleManager(); - lifecycleManager0.startServices(INTRODUCER); - lifecycleManager1.startServices(INTRODUCEE1); - lifecycleManager2.startServices(INTRODUCEE2); - lifecycleManager0.waitForStartup(); - lifecycleManager1.waitForStartup(); - lifecycleManager2.waitForStartup(); - } - - private void stopLifecycles() throws InterruptedException { - // Clean up - lifecycleManager0.stopServices(); - lifecycleManager1.stopServices(); - lifecycleManager2.stopServices(); - lifecycleManager0.waitForShutdown(); - lifecycleManager1.waitForShutdown(); - lifecycleManager2.waitForShutdown(); - } - private void addTransportProperties() throws DbException, IOException, TimeoutException { - TransportPropertyManager tpm0 = t0.getTransportPropertyManager(); - TransportPropertyManager tpm1 = t1.getTransportPropertyManager(); - TransportPropertyManager tpm2 = t2.getTransportPropertyManager(); + TransportPropertyManager tpm0 = c0.getTransportPropertyManager(); + TransportPropertyManager tpm1 = c1.getTransportPropertyManager(); + TransportPropertyManager tpm2 = c2.getTransportPropertyManager(); TransportProperties tp = new TransportProperties( Collections.singletonMap("key", "value")); tpm0.mergeLocalProperties(TRANSPORT_ID, tp); - deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1"); - deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2"); + sync0To1(1, true); + sync0To2(1, true); tpm1.mergeLocalProperties(TRANSPORT_ID, tp); - deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0"); + sync1To0(1, true); tpm2.mergeLocalProperties(TRANSPORT_ID, tp); - deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0"); - } - - private void addListeners(boolean accept1, boolean accept2) { - // listen to events - listener0 = new IntroducerListener(); - t0.getEventBus().addListener(listener0); - listener1 = new IntroduceeListener(1, accept1); - t1.getEventBus().addListener(listener1); - listener2 = new IntroduceeListener(2, accept2); - t2.getEventBus().addListener(listener2); - } - - private void getDefaultIdentities() throws DbException { - author0 = identityManager0.getLocalAuthor(); - author1 = identityManager1.getLocalAuthor(); - author2 = identityManager2.getLocalAuthor(); - - } - - private void addDefaultContacts() throws DbException { - // Add introducees as contacts - contactId1 = contactManager0.addContact(author1, - author0.getId(), master, clock.currentTimeMillis(), true, - true, true - ); - contactId2 = contactManager0.addContact(author2, - author0.getId(), master, clock.currentTimeMillis(), true, - true, true - ); - // Add introducer back - contactId0 = contactManager1.addContact(author0, - author1.getId(), master, clock.currentTimeMillis(), true, - true, true - ); - ContactId contactId02 = contactManager2.addContact(author0, - author2.getId(), master, clock.currentTimeMillis(), true, - true, true - ); - assertTrue(contactId0.equals(contactId02)); - } - - private void deliverMessage(SyncSessionFactory fromSync, ContactId fromId, - SyncSessionFactory toSync, ContactId toId, String debug) - throws IOException, TimeoutException { - deliverMessage(fromSync, fromId, toSync, toId, 1, debug); - } - - private void deliverMessage(SyncSessionFactory fromSync, ContactId fromId, - SyncSessionFactory toSync, ContactId toId) - throws IOException, TimeoutException { - deliverMessage(fromSync, fromId, toSync, toId, 1, null); - } - - private void deliverMessage(SyncSessionFactory fromSync, ContactId fromId, - SyncSessionFactory toSync, ContactId toId, int num, - @Nullable String debug) - throws IOException, TimeoutException { - - if (debug != null) LOG.info("TEST: Sending message from " + debug); - - ByteArrayOutputStream out = new ByteArrayOutputStream(); - // Create an outgoing sync session - SyncSession sessionFrom = - fromSync.createSimplexOutgoingSession(toId, MAX_LATENCY, out); - // Write whatever needs to be written - sessionFrom.run(); - out.close(); - - ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); - // Create an incoming sync session - SyncSession sessionTo = toSync.createIncomingSession(fromId, in); - // Read whatever needs to be read - sessionTo.run(); - in.close(); - - // wait for [num] message(s) to actually arrive - msgWaiter.await(TIMEOUT, num); + sync2To0(1, true); } private void assertDefaultUiMessages() throws DbException { assertEquals(2, introductionManager0.getIntroductionMessages( - contactId1).size()); + contactId1From0).size()); assertEquals(2, introductionManager0.getIntroductionMessages( - contactId2).size()); + contactId2From0).size()); assertEquals(2, introductionManager1.getIntroductionMessages( - contactId0).size()); + contactId0From1).size()); assertEquals(2, introductionManager2.getIntroductionMessages( - contactId0).size()); + contactId0From2).size()); + } + + private void addListeners(boolean accept1, boolean accept2) { + // listen to events + listener0 = new IntroducerListener(); + c0.getEventBus().addListener(listener0); + listener1 = new IntroduceeListener(1, accept1); + c1.getEventBus().addListener(listener1); + listener2 = new IntroduceeListener(2, accept2); + c2.getEventBus().addListener(listener2); } private class IntroduceeListener implements EventListener { @@ -1135,15 +845,7 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest { @Override public void eventOccurred(Event e) { - if (e instanceof MessageStateChangedEvent) { - MessageStateChangedEvent event = (MessageStateChangedEvent) e; - State s = event.getState(); - if ((s == DELIVERED || s == INVALID) && !event.isLocal()) { - LOG.info("TEST: Introducee" + introducee + - " received message"); - msgWaiter.resume(); - } - } else if (e instanceof IntroductionRequestReceivedEvent) { + if (e instanceof IntroductionRequestReceivedEvent) { IntroductionRequestReceivedEvent introEvent = ((IntroductionRequestReceivedEvent) e); requestReceived = true; @@ -1181,7 +883,8 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest { } else if (e instanceof IntroductionSucceededEvent) { succeeded = true; Contact contact = ((IntroductionSucceededEvent) e).getContact(); - eventWaiter.assertFalse(contact.getId().equals(contactId0)); + eventWaiter + .assertFalse(contact.getId().equals(contactId0From1)); eventWaiter.assertTrue(contact.isActive()); eventWaiter.resume(); } else if (e instanceof IntroductionAbortedEvent) { @@ -1199,18 +902,13 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest { @Override public void eventOccurred(Event e) { - if (e instanceof MessageStateChangedEvent) { - MessageStateChangedEvent event = (MessageStateChangedEvent) e; - if (event.getState() == DELIVERED && !event.isLocal()) { - LOG.info("TEST: Introducer received message"); - msgWaiter.resume(); - } - } else if (e instanceof IntroductionResponseReceivedEvent) { + if (e instanceof IntroductionResponseReceivedEvent) { ContactId c = - ((IntroductionResponseReceivedEvent) e).getContactId(); - if (c.equals(contactId1)) { + ((IntroductionResponseReceivedEvent) e) + .getContactId(); + if (c.equals(contactId1From0)) { response1Received = true; - } else if (c.equals(contactId2)) { + } else if (c.equals(contactId2From0)) { response2Received = true; } eventWaiter.resume(); @@ -1219,26 +917,26 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest { eventWaiter.resume(); } } + } - private void decreaseOutgoingMessageCounter(ClientHelper clientHelper, - GroupId g, int num) throws FormatException, DbException { - BdfDictionary gD = clientHelper.getGroupMetadataAsDictionary(g); + private void decreaseOutgoingMessageCounter(ClientHelper ch, GroupId g, + int num) throws FormatException, DbException { + BdfDictionary gD = ch.getGroupMetadataAsDictionary(g); LOG.warning(gD.toString()); BdfDictionary queue = gD.getDictionary(QUEUE_STATE_KEY); queue.put("nextOut", queue.getLong("nextOut") - num); gD.put(QUEUE_STATE_KEY, queue); - clientHelper.mergeGroupMetadata(g, gD); + ch.mergeGroupMetadata(g, gD); } - private Entry<MessageId, BdfDictionary> getMessageFor(Contact contact, - long type) throws FormatException, DbException { + private Entry<MessageId, BdfDictionary> getMessageFor(ClientHelper ch, + Contact contact, long type) throws FormatException, DbException { Entry<MessageId, BdfDictionary> response = null; Group g = introductionGroupFactory .createIntroductionGroup(contact); - ClientHelper clientHelper0 = t0.getClientHelper(); Map<MessageId, BdfDictionary> map = - clientHelper0.getMessageMetadataAsDictionary(g.getId()); + ch.getMessageMetadataAsDictionary(g.getId()); for (Entry<MessageId, BdfDictionary> entry : map.entrySet()) { if (entry.getValue().getLong(TYPE) == type) { response = entry; @@ -1248,17 +946,4 @@ public class IntroductionIntegrationTest extends BriarIntegrationTest { return response; } - private void injectEagerSingletons( - IntroductionIntegrationTestComponent component) { - - component.inject(new LifecycleModule.EagerSingletons()); - component.inject(new LifecycleModule.EagerSingletons()); - component.inject(new IntroductionModule.EagerSingletons()); - component.inject(new CryptoModule.EagerSingletons()); - component.inject(new ContactModule.EagerSingletons()); - component.inject(new TransportModule.EagerSingletons()); - component.inject(new SyncModule.EagerSingletons()); - component.inject(new SystemModule.EagerSingletons()); - component.inject(new PropertiesModule.EagerSingletons()); - } } diff --git a/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTestComponent.java b/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTestComponent.java deleted file mode 100644 index 1741364824258fd826122d5814cb27bd133144d6..0000000000000000000000000000000000000000 --- a/briar-android-tests/src/test/java/org/briarproject/introduction/IntroductionIntegrationTestComponent.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.briarproject.introduction; - -import org.briarproject.TestDatabaseModule; -import org.briarproject.TestPluginsModule; -import org.briarproject.TestSeedProviderModule; -import org.briarproject.api.clients.ClientHelper; -import org.briarproject.api.clients.MessageTracker; -import org.briarproject.api.contact.ContactManager; -import org.briarproject.api.db.DatabaseComponent; -import org.briarproject.api.event.EventBus; -import org.briarproject.api.identity.IdentityManager; -import org.briarproject.api.introduction.IntroductionManager; -import org.briarproject.api.lifecycle.LifecycleManager; -import org.briarproject.api.properties.TransportPropertyManager; -import org.briarproject.api.sync.SyncSessionFactory; -import org.briarproject.clients.ClientsModule; -import org.briarproject.contact.ContactModule; -import org.briarproject.crypto.CryptoModule; -import org.briarproject.data.DataModule; -import org.briarproject.db.DatabaseModule; -import org.briarproject.event.EventModule; -import org.briarproject.identity.IdentityModule; -import org.briarproject.lifecycle.LifecycleModule; -import org.briarproject.messaging.MessagingModule; -import org.briarproject.properties.PropertiesModule; -import org.briarproject.sync.SyncModule; -import org.briarproject.system.SystemModule; -import org.briarproject.transport.TransportModule; - -import javax.inject.Singleton; - -import dagger.Component; - -@Singleton -@Component(modules = { - TestDatabaseModule.class, - TestPluginsModule.class, - TestSeedProviderModule.class, - LifecycleModule.class, - IntroductionModule.class, - DatabaseModule.class, - CryptoModule.class, - EventModule.class, - ContactModule.class, - IdentityModule.class, - TransportModule.class, - ClientsModule.class, - SyncModule.class, - SystemModule.class, - DataModule.class, - PropertiesModule.class, - MessagingModule.class -}) -interface IntroductionIntegrationTestComponent { - - void inject(IntroductionIntegrationTest testCase); - - void inject(ContactModule.EagerSingletons init); - - void inject(CryptoModule.EagerSingletons init); - - void inject(IntroductionModule.EagerSingletons init); - - void inject(LifecycleModule.EagerSingletons init); - - void inject(PropertiesModule.EagerSingletons init); - - void inject(SyncModule.EagerSingletons init); - - void inject(SystemModule.EagerSingletons init); - - void inject(TransportModule.EagerSingletons init); - - LifecycleManager getLifecycleManager(); - - EventBus getEventBus(); - - IdentityManager getIdentityManager(); - - ContactManager getContactManager(); - - IntroductionManager getIntroductionManager(); - - TransportPropertyManager getTransportPropertyManager(); - - MessageTracker getMessageTracker(); - - SyncSessionFactory getSyncSessionFactory(); - - /* the following methods are only needed to manually construct messages */ - - DatabaseComponent getDatabaseComponent(); - - ClientHelper getClientHelper(); - - MessageSender getMessageSender(); - - IntroductionGroupFactory getIntroductionGroupFactory(); -} diff --git a/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java b/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java index 12cc01323d3cf012f617a03981525ac4a620612f..a7e7e3db73dc4c56373b620665340c8216889ce7 100644 --- a/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java +++ b/briar-api/src/org/briarproject/api/introduction/IntroductionManager.java @@ -8,6 +8,7 @@ import org.briarproject.api.db.DbException; import org.briarproject.api.messaging.ConversationManager.ConversationClient; import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.ClientId; +import org.jetbrains.annotations.Nullable; import java.util.Collection; @@ -20,7 +21,7 @@ public interface IntroductionManager extends ConversationClient { /** * sends two initial introduction messages */ - void makeIntroduction(Contact c1, Contact c2, String msg, + void makeIntroduction(Contact c1, Contact c2, @Nullable String msg, final long timestamp) throws DbException, FormatException; diff --git a/briar-api/src/org/briarproject/api/sharing/SharingManager.java b/briar-api/src/org/briarproject/api/sharing/SharingManager.java index 66b6ef82f6c275763d6f8a9e5c2720836d0c4b93..783e3ba3eba6c8c072516d9f92fe62a6f3d162f6 100644 --- a/briar-api/src/org/briarproject/api/sharing/SharingManager.java +++ b/briar-api/src/org/briarproject/api/sharing/SharingManager.java @@ -7,6 +7,7 @@ import org.briarproject.api.db.DbException; import org.briarproject.api.messaging.ConversationManager.ConversationClient; import org.briarproject.api.nullsafety.NotNullByDefault; import org.briarproject.api.sync.GroupId; +import org.jetbrains.annotations.Nullable; import java.util.Collection; @@ -19,7 +20,7 @@ public interface SharingManager<S extends Shareable> * and sends an optional message along with it. */ void sendInvitation(GroupId groupId, ContactId contactId, - String message) throws DbException; + @Nullable String message) throws DbException; /** * Responds to a pending group invitation diff --git a/briar-tests/src/org/briarproject/BriarTestCase.java b/briar-tests/src/org/briarproject/BriarTestCase.java index e847c546bfaf110fb871369c0764228fe8349ab0..745628c539be797a2a4cdb753250ca8344945719 100644 --- a/briar-tests/src/org/briarproject/BriarTestCase.java +++ b/briar-tests/src/org/briarproject/BriarTestCase.java @@ -9,6 +9,7 @@ public abstract class BriarTestCase { public BriarTestCase() { // Ensure exceptions thrown on worker threads cause tests to fail UncaughtExceptionHandler fail = new UncaughtExceptionHandler() { + @Override public void uncaughtException(Thread thread, Throwable throwable) { throwable.printStackTrace(); fail(); diff --git a/briar-tests/src/org/briarproject/TestUtils.java b/briar-tests/src/org/briarproject/TestUtils.java index 95a6d1ac4cf1ef42e186e0c8dd5603e3f45acb92..562d27685dfa1049380846f136ec98c58fecefa0 100644 --- a/briar-tests/src/org/briarproject/TestUtils.java +++ b/briar-tests/src/org/briarproject/TestUtils.java @@ -1,13 +1,19 @@ package org.briarproject; import org.briarproject.api.UniqueId; +import org.briarproject.api.clients.MessageTracker; +import org.briarproject.api.clients.MessageTracker.GroupCount; import org.briarproject.api.crypto.SecretKey; +import org.briarproject.api.db.DbException; +import org.briarproject.api.sync.GroupId; import org.briarproject.util.IoUtils; import java.io.File; import java.util.Random; import java.util.concurrent.atomic.AtomicInteger; +import static org.junit.Assert.assertEquals; + public class TestUtils { private static final AtomicInteger nextTestDir = @@ -44,4 +50,20 @@ public class TestUtils { public static SecretKey getSecretKey() { return new SecretKey(getRandomBytes(SecretKey.LENGTH)); } + + public static void assertGroupCount(MessageTracker tracker, GroupId g, + long msgCount, long unreadCount, long latestMsgTime) + throws DbException { + GroupCount groupCount = tracker.getGroupCount(g); + assertEquals(msgCount, groupCount.getMsgCount()); + assertEquals(unreadCount, groupCount.getUnreadCount()); + assertEquals(latestMsgTime, groupCount.getLatestMsgTime()); + } + + public static void assertGroupCount(MessageTracker tracker, GroupId g, + long msgCount, long unreadCount) throws DbException { + GroupCount c1 = tracker.getGroupCount(g); + assertEquals(msgCount, c1.getMsgCount()); + assertEquals(unreadCount, c1.getUnreadCount()); + } }