Compare commits

..

1 Commits

Author SHA1 Message Date
str4d
0e32139a89 Second part of BQP UI improvements: zxing viewfinder. 2016-05-20 15:01:48 +12:00
558 changed files with 8065 additions and 27717 deletions

View File

@@ -68,12 +68,6 @@
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
</XML>
<codeStyleSettings language="Groovy">
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true" />
<option name="SMART_TABS" value="true" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="RIGHT_MARGIN" value="80" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />

View File

@@ -1,4 +1,5 @@
apply plugin: 'com.android.library'
apply plugin: 'witness'
apply plugin: 'com.neenbedankt.android-apt'
android {
@@ -6,15 +7,20 @@ android {
buildToolsVersion "23.0.3"
defaultConfig {
minSdkVersion 14
proguardFiles getDefaultProguardFile('proguard-android.txt'), '../briar-android/proguard-rules.txt'
consumerProguardFiles getDefaultProguardFile('proguard-android.txt'), '../briar-android/proguard-rules.txt'
minSdkVersion 9
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
dexOptions {
incremental true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
@@ -22,12 +28,23 @@ android {
}
dependencies {
testCompile project(':briar-api')
testCompile project(':briar-core')
compile fileTree(dir: 'libs', include: ['*.jar'])
compile project(':briar-api')
compile project(':briar-core')
testCompile 'junit:junit:4.12'
testCompile 'net.jodah:concurrentunit:0.4.2'
testCompile 'com.android.support:appcompat-v7:23.2.1'
compile 'com.android.support:appcompat-v7:23.2.1'
testApt 'com.google.dagger:dagger-compiler:2.0.2'
provided 'javax.annotation:jsr250-api:1.0'
testCompile project(':briar-tests')
}
dependencyVerification {
verify = [
'com.android.support:appcompat-v7:00f9d93acacd6731f309724054bf51492814b4b2869f16d7d5c0038dcb8c9a0d',
'com.android.support:support-v4:81ce890f26d35c75ad17d0f998a7e3230330c3b41e0b629566bc744bee89e448',
'com.android.support:animated-vector-drawable:06d1963b85aa917099d7757e6a7b3e4dc06889413dc747f625ae8683606db3a1',
'com.android.support:support-vector-drawable:799bafe4c3de812386f0b291f744d5d6876452722dd40189b9ab87dbbf594ea1',
'com.android.support:support-annotations:786ab0d060774fb95cfdaf4878771e14b85733b1af9d72a4aae762dc7c1dff9f',
]
}

17
briar-android-tests/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /home/ernir/dev/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@@ -1,656 +0,0 @@
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.KeyPair;
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 {
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(ForumSharingIntegrationTest.class.getName());
private BlogManagerTestComponent t0, t1;
@Rule
public ExpectedException thrown = ExpectedException.none();
@Before
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();
}
@Test
public void testPersonalBlogInitialisation() throws Exception {
startLifecycles();
defaultInit();
Collection<Blog> blogs0 = blogManager0.getBlogs();
assertEquals(2, blogs0.size());
Iterator<Blog> i0 = blogs0.iterator();
assertEquals(author0, i0.next().getAuthor());
assertEquals(author1, i0.next().getAuthor());
Collection<Blog> blogs1 = blogManager1.getBlogs();
assertEquals(2, blogs1.size());
Iterator<Blog> i1 = blogs1.iterator();
assertEquals(author1, i1.next().getAuthor());
assertEquals(author0, i1.next().getAuthor());
assertEquals(blog0, blogManager0.getPersonalBlog(author0));
assertEquals(blog0, blogManager1.getPersonalBlog(author0));
assertEquals(blog1, blogManager0.getPersonalBlog(author1));
assertEquals(blog1, blogManager1.getPersonalBlog(author1));
assertEquals(blog0, blogManager0.getBlog(blog0.getId()));
assertEquals(blog0, blogManager1.getBlog(blog0.getId()));
assertEquals(blog1, blogManager0.getBlog(blog1.getId()));
assertEquals(blog1, blogManager1.getBlog(blog1.getId()));
assertEquals(1, blogManager0.getBlogs(author0).size());
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 =
blogManager0.getPostHeaders(blog0.getId());
assertEquals(0, headers0.size());
// add a post to blog0
BlogPost p = blogPostFactory
.createBlogPost(blog0.getId(), clock.currentTimeMillis(), null,
author0, body);
blogManager0.addLocalPost(p);
// check that post is now in blog0
headers0 = blogManager0.getPostHeaders(blog0.getId());
assertEquals(1, headers0.size());
// check that body is there
assertEquals(body, blogManager0.getPostBody(p.getMessage().getId()));
// make sure that blog0 at author1 doesn't have the post yet
Collection<BlogPostHeader> headers1 =
blogManager1.getPostHeaders(blog0.getId());
assertEquals(0, headers1.size());
// sync the post over
sync0To1();
deliveryWaiter.await(TIMEOUT, 1);
// make sure post arrived
headers1 = blogManager1.getPostHeaders(blog0.getId());
assertEquals(1, headers1.size());
assertEquals(POST, headers1.iterator().next().getType());
// 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
.createBlogPost(blog1.getId(), clock.currentTimeMillis(), null,
author0, body);
blogManager0.addLocalPost(p);
// check that post is now in blog1
Collection<BlogPostHeader> headers0 =
blogManager0.getPostHeaders(blog1.getId());
assertEquals(1, headers0.size());
// sync the post over
sync0To1();
validationWaiter.await(TIMEOUT, 1);
// 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 testAddAndRemoveBlog() throws Exception {
startLifecycles();
defaultInit();
String name = "Test Blog";
String desc = "Description";
// add blog
Blog blog = blogManager0.addBlog(author0, name, desc);
Collection<Blog> blogs0 = blogManager0.getBlogs();
assertEquals(3, blogs0.size());
assertTrue(blogs0.contains(blog));
assertEquals(2, blogManager0.getBlogs(author0).size());
assertTrue(blogManager0.canBeRemoved(blog.getId()));
// remove blog
blogManager0.removeBlog(blog);
blogs0 = blogManager0.getBlogs();
assertEquals(2, blogs0.size());
assertFalse(blogs0.contains(blog));
assertEquals(1, blogManager0.getBlogs(author0).size());
stopLifecycles();
}
@Test
public void testCanNotRemoveContactsPersonalBlog() throws Exception {
startLifecycles();
defaultInit();
assertFalse(blogManager0.canBeRemoved(blog1.getId()));
assertFalse(blogManager1.canBeRemoved(blog0.getId()));
// the following two calls should throw a DbException now
thrown.expect(DbException.class);
blogManager0.removeBlog(blog1);
blogManager1.removeBlog(blog0);
// 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
.createBlogPost(blog0.getId(), clock.currentTimeMillis(), null,
author0, body);
blogManager0.addLocalPost(p);
// sync the post over
sync0To1();
deliveryWaiter.await(TIMEOUT, 1);
// make sure post arrived
Collection<BlogPostHeader> headers1 =
blogManager1.getPostHeaders(blog0.getId());
assertEquals(1, headers1.size());
assertEquals(POST, headers1.iterator().next().getType());
// 1 adds a comment to that blog post
String comment = "This is a comment on a blog post!";
blogManager1
.addLocalComment(author1, blog1.getId(), comment,
headers1.iterator().next());
// sync comment over
sync1To0();
deliveryWaiter.await(TIMEOUT, 2);
// make sure comment and wrapped post arrived
Collection<BlogPostHeader> headers0 =
blogManager0.getPostHeaders(blog1.getId());
assertEquals(1, headers0.size());
assertEquals(COMMENT, headers0.iterator().next().getType());
BlogCommentHeader h = (BlogCommentHeader) headers0.iterator().next();
assertEquals(author0, h.getParent().getAuthor());
// ensure that body can be retrieved from wrapped post
assertEquals(body, blogManager0.getPostBody(h.getParentId()));
// 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
.createBlogPost(blog0.getId(), clock.currentTimeMillis(), null,
author0, body);
blogManager0.addLocalPost(p);
// get header of own post
Collection<BlogPostHeader> headers0 =
blogManager0.getPostHeaders(blog0.getId());
assertEquals(1, headers0.size());
BlogPostHeader header = headers0.iterator().next();
// add a comment on own post
String comment = "This is a comment on my own blog post!";
blogManager0
.addLocalComment(author0, blog0.getId(), comment, header);
// sync the post and comment over
sync0To1();
deliveryWaiter.await(TIMEOUT, 2);
// make sure post arrived
Collection<BlogPostHeader> headers1 =
blogManager1.getPostHeaders(blog0.getId());
assertEquals(2, headers1.size());
for (BlogPostHeader h : headers1) {
if (h.getType() == POST) {
assertEquals(body, blogManager1.getPostBody(h.getId()));
} else {
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
.createBlogPost(blog0.getId(), clock.currentTimeMillis(), null,
author0, body);
blogManager0.addLocalPost(p);
// sync the post over
sync0To1();
deliveryWaiter.await(TIMEOUT, 1);
// make sure post arrived
Collection<BlogPostHeader> headers1 =
blogManager1.getPostHeaders(blog0.getId());
assertEquals(1, headers1.size());
assertEquals(POST, headers1.iterator().next().getType());
// 1 reblogs that blog post
blogManager1
.addLocalComment(author1, blog1.getId(), null,
headers1.iterator().next());
// sync comment over
sync1To0();
deliveryWaiter.await(TIMEOUT, 2);
// make sure comment and wrapped post arrived
Collection<BlogPostHeader> headers0 =
blogManager0.getPostHeaders(blog1.getId());
assertEquals(1, headers0.size());
// get header of comment
BlogPostHeader cHeader = headers0.iterator().next();
assertEquals(COMMENT, cHeader.getType());
// comment on the comment
String comment = "This is a comment on a reblogged post.";
blogManager0
.addLocalComment(author0, blog0.getId(), comment, cHeader);
// sync comment over
sync0To1();
deliveryWaiter.await(TIMEOUT, 3);
// check that comment arrived
headers1 =
blogManager1.getPostHeaders(blog0.getId());
assertEquals(2, headers1.size());
// get header of comment
cHeader = null;
for (BlogPostHeader h : headers1) {
if (h.getType() == COMMENT) {
cHeader = h;
}
}
assertTrue(cHeader != null);
// another comment on the comment
String comment2 = "This is a comment on a comment.";
blogManager1.addLocalComment(author1, blog1.getId(), comment2, cHeader);
// sync comment over
sync1To0();
deliveryWaiter.await(TIMEOUT, 4);
// make sure new comment arrived
headers0 =
blogManager0.getPostHeaders(blog1.getId());
assertEquals(2, headers0.size());
boolean satisfied = false;
for (BlogPostHeader h : headers0) {
assertEquals(COMMENT, h.getType());
BlogCommentHeader c = (BlogCommentHeader) h;
if (c.getComment() != null && c.getComment().equals(comment2)) {
assertEquals(author0, c.getParent().getAuthor());
assertEquals(WRAPPED_COMMENT, c.getParent().getType());
assertEquals(comment,
((BlogCommentHeader) c.getParent()).getComment());
assertEquals(WRAPPED_COMMENT,
((BlogCommentHeader) c.getParent()).getParent()
.getType());
assertEquals(WRAPPED_POST,
((BlogCommentHeader) ((BlogCommentHeader) c
.getParent()).getParent()).getParent()
.getType());
satisfied = true;
}
}
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
.createBlogPost(blog0.getId(), clock.currentTimeMillis(), null,
author0, body);
blogManager0.addLocalPost(p);
// sync the post over
sync0To1();
deliveryWaiter.await(TIMEOUT, 1);
// make sure post arrived
Collection<BlogPostHeader> headers1 =
blogManager1.getPostHeaders(blog0.getId());
assertEquals(1, headers1.size());
assertEquals(POST, headers1.iterator().next().getType());
// 1 reblogs that blog post with a comment
String comment = "This is a comment on a post.";
blogManager1
.addLocalComment(author1, blog1.getId(), comment,
headers1.iterator().next());
// get comment from own blog
headers1 = blogManager1.getPostHeaders(blog1.getId());
assertEquals(1, headers1.size());
assertEquals(COMMENT, headers1.iterator().next().getType());
BlogCommentHeader ch = (BlogCommentHeader) headers1.iterator().next();
assertEquals(comment, ch.getComment());
comment = "This is a comment on a post with a comment.";
blogManager1.addLocalComment(author1, blog1.getId(), comment, ch);
// sync both comments over (2 comments + 1 wrapped post)
sync1To0();
deliveryWaiter.await(TIMEOUT, 3);
// 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 {
addDefaultIdentities();
addDefaultContacts();
listenToEvents();
}
private void addDefaultIdentities() throws DbException {
KeyPair keyPair0 = crypto.generateSignatureKeyPair();
byte[] publicKey0 = keyPair0.getPublic().getEncoded();
byte[] privateKey0 = keyPair0.getPrivate().getEncoded();
author0 = authorFactory
.createLocalAuthor(AUTHOR1, publicKey0, privateKey0);
identityManager0.addLocalAuthor(author0);
blog0 = blogFactory.createPersonalBlog(author0);
KeyPair keyPair1 = crypto.generateSignatureKeyPair();
byte[] publicKey1 = keyPair1.getPublic().getEncoded();
byte[] privateKey1 = keyPair1.getPrivate().getEncoded();
author1 = authorFactory
.createLocalAuthor(AUTHOR2, publicKey1, privateKey1);
identityManager1.addLocalAuthor(author1);
blog1 = blogFactory.createPersonalBlog(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();
lifecycleManager1.startServices();
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());
}
}

View File

@@ -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();
}

View File

@@ -1,744 +0,0 @@
package org.briarproject;
import net.jodah.concurrentunit.Waiter;
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.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.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.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.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 BriarTestCase {
private LifecycleManager lifecycleManager0, lifecycleManager1,
lifecycleManager2;
private SyncSessionFactory sync0, sync1, sync2;
private BlogManager blogManager0, blogManager1, blogManager2;
private ContactManager contactManager0, contactManager1, contactManager2;
private Contact contact1, contact2, contact01, contact02;
private ContactId contactId1, contactId2, contactId01, contactId02;
private IdentityManager identityManager0, identityManager1,
identityManager2;
private LocalAuthor author0, author1, author2;
private Blog blog0, blog1, blog2;
private SharerListener listener0, listener2;
private InviteeListener listener1;
@Inject
Clock clock;
@Inject
AuthorFactory authorFactory;
@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();
blogManager2 = t2.getBlogManager();
blogSharingManager0 = t0.getBlogSharingManager();
blogSharingManager1 = t1.getBlogSharingManager();
blogSharingManager2 = t2.getBlogSharingManager();
sync0 = t0.getSyncSessionFactory();
sync1 = t1.getSyncSessionFactory();
sync2 = t2.getSyncSessionFactory();
// initialize waiters fresh for each test
eventWaiter = new Waiter();
msgWaiter = new Waiter();
}
@Test
public void testPersonalBlogCannotBeSharedWithOwner() throws Exception {
startLifecycles();
defaultInit(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));
// create invitation
blogSharingManager0
.sendInvitation(blog1.getId(), contactId1, "Hi!");
// sync invitation
sync0To1();
// 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);
// send invitation
blogSharingManager0
.sendInvitation(blog2.getId(), contactId1, "Hi!");
// invitee has own blog and that of the sharer
assertEquals(2, blogManager1.getBlogs().size());
// sync first request message
sync0To1();
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.requestReceived);
// sync response back
sync1To0();
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.responseReceived);
// blog was added successfully
assertEquals(0, blogSharingManager0.getInvitations().size());
assertEquals(3, blogManager1.getBlogs().size());
// invitee has one invitation message from sharer
List<InvitationMessage> list =
new ArrayList<>(blogSharingManager1
.getInvitationMessages(contactId01));
assertEquals(2, list.size());
// check other things are alright with the message
for (InvitationMessage m : list) {
if (m instanceof BlogInvitationRequest) {
BlogInvitationRequest invitation =
(BlogInvitationRequest) m;
assertFalse(invitation.isAvailable());
assertEquals(blog2.getAuthor().getName(),
invitation.getBlogAuthorName());
assertEquals(contactId1, invitation.getContactId());
assertEquals("Hi!", invitation.getMessage());
} else {
BlogInvitationResponse response =
(BlogInvitationResponse) m;
assertEquals(contactId01, response.getContactId());
assertTrue(response.wasAccepted());
assertTrue(response.isLocal());
}
}
// sharer has own invitation message and response
assertEquals(2,
blogSharingManager0.getInvitationMessages(contactId1)
.size());
// blog can not be shared again
assertFalse(blogSharingManager0.canBeShared(blog2.getId(), contact1));
assertFalse(blogSharingManager1.canBeShared(blog2.getId(), contact01));
stopLifecycles();
}
@Test
public void testDeclinedSharing() throws Exception {
startLifecycles();
// initialize and let invitee deny all requests
defaultInit(false);
// send invitation
blogSharingManager0
.sendInvitation(blog2.getId(), contactId1, null);
// sync first request message
sync0To1();
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.requestReceived);
// sync response back
sync1To0();
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.responseReceived);
// blog was not added
assertEquals(0, blogSharingManager0.getInvitations().size());
assertEquals(2, blogManager1.getBlogs().size());
// blog is no longer available to invitee who declined
assertEquals(0, blogSharingManager1.getInvitations().size());
// invitee has one invitation message from sharer and one response
List<InvitationMessage> list =
new ArrayList<>(blogSharingManager1
.getInvitationMessages(contactId01));
assertEquals(2, list.size());
// check things are alright with the message
for (InvitationMessage m : list) {
if (m instanceof BlogInvitationRequest) {
BlogInvitationRequest invitation =
(BlogInvitationRequest) m;
assertFalse(invitation.isAvailable());
assertEquals(blog2.getAuthor().getName(),
invitation.getBlogAuthorName());
assertEquals(contactId1, invitation.getContactId());
assertEquals(null, invitation.getMessage());
} else {
BlogInvitationResponse response =
(BlogInvitationResponse) m;
assertEquals(contactId01, response.getContactId());
assertFalse(response.wasAccepted());
assertTrue(response.isLocal());
}
}
// sharer has own invitation message and response
assertEquals(2,
blogSharingManager0.getInvitationMessages(contactId1)
.size());
// blog can be shared again
assertTrue(blogSharingManager0.canBeShared(blog2.getId(), contact1));
stopLifecycles();
}
@Test
public void testInviteeLeavesAfterFinished() throws Exception {
startLifecycles();
// initialize and let invitee accept all requests
defaultInit(true);
// send invitation
blogSharingManager0
.sendInvitation(blog2.getId(), contactId1, "Hi!");
// sync first request message
sync0To1();
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.requestReceived);
// sync response back
sync1To0();
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.responseReceived);
// blog was added successfully
assertEquals(0, blogSharingManager0.getInvitations().size());
assertEquals(3, blogManager1.getBlogs().size());
assertTrue(blogManager1.getBlogs().contains(blog2));
// sharer shares blog with invitee
assertTrue(blogSharingManager0.getSharedWith(blog2.getId())
.contains(contact1));
// invitee gets blog shared by sharer
assertTrue(blogSharingManager1.getSharedBy(blog2.getId())
.contains(contact01));
// invitee un-subscribes from blog
blogManager1.removeBlog(blog2);
// send leave message to sharer
sync1To0();
// blog is gone
assertEquals(0, blogSharingManager0.getInvitations().size());
assertEquals(2, blogManager1.getBlogs().size());
// sharer no longer shares blog with invitee
assertFalse(blogSharingManager0.getSharedWith(blog2.getId())
.contains(contact1));
// invitee no longer gets blog shared by sharer
assertFalse(blogSharingManager1.getSharedBy(blog2.getId())
.contains(contact01));
// blog can be shared again
assertTrue(blogSharingManager0.canBeShared(blog2.getId(), contact1));
assertTrue(blogSharingManager1.canBeShared(blog2.getId(), contact01));
stopLifecycles();
}
@Test
public void testInvitationForExistingBlog() throws Exception {
startLifecycles();
// initialize and let invitee accept all requests
defaultInit(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
);
assertEquals(3, blogManager1.getBlogs().size());
// sharer sends invitation for 2's blog to 1
blogSharingManager0
.sendInvitation(blog2.getId(), contactId1, "Hi!");
// sync first request message
sync0To1();
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.requestReceived);
// make sure blog2 is shared by 0
Collection<Contact> contacts =
blogSharingManager1.getSharedBy(blog2.getId());
assertEquals(1, contacts.size());
assertTrue(contacts.contains(contact01));
// make sure 1 knows that they have blog2 already
Collection<InvitationMessage> messages =
blogSharingManager1.getInvitationMessages(contactId01);
assertEquals(2, messages.size());
assertEquals(blog2, blogManager1.getBlog(blog2.getId()));
// sync response back
sync1To0();
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);
// send invitation
blogSharingManager0
.sendInvitation(blog2.getId(), contactId1, "Hi!");
// sync first request message
sync0To1();
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.requestReceived);
// sync response back
sync1To0();
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.responseReceived);
// blog was added successfully and is shared both ways
assertEquals(3, blogManager1.getBlogs().size());
Collection<Contact> sharedWith =
blogSharingManager0.getSharedWith(blog2.getId());
assertEquals(1, sharedWith.size());
assertEquals(contact1, sharedWith.iterator().next());
Collection<Contact> sharedBy =
blogSharingManager1.getSharedBy(blog2.getId());
assertEquals(1, sharedBy.size());
assertEquals(contact01, sharedBy.iterator().next());
// shared blog can be removed
assertTrue(blogManager1.canBeRemoved(blog2.getId()));
// invitee removes blog again
blogManager1.removeBlog(blog2);
// sync LEAVE message
sync1To0();
// 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);
// 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!");
// sync first request message
sync0To1();
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.requestReceived);
// make sure blog2 is shared by 0
Collection<Contact> contacts =
blogSharingManager1.getSharedBy(blog2.getId());
assertEquals(1, contacts.size());
assertTrue(contacts.contains(contact01));
// sync response back
sync1To0();
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.responseReceived);
// blog was added and can be removed
assertEquals(3, blogManager1.getBlogs().size());
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
);
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 {
volatile boolean requestReceived = false;
volatile boolean responseReceived = false;
@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) {
BlogInvitationResponseReceivedEvent event =
(BlogInvitationResponseReceivedEvent) e;
eventWaiter.assertEquals(contactId1, event.getContactId());
responseReceived = true;
eventWaiter.resume();
}
// this is only needed for tests where a blog is re-shared
else if (e instanceof BlogInvitationReceivedEvent) {
BlogInvitationReceivedEvent event =
(BlogInvitationReceivedEvent) e;
eventWaiter.assertEquals(contactId1, event.getContactId());
requestReceived = true;
Blog b = event.getBlog();
try {
Contact c = contactManager0.getContact(contactId1);
blogSharingManager0.respondToInvitation(b, c, true);
} catch (DbException ex) {
eventWaiter.rethrow(ex);
} finally {
eventWaiter.resume();
}
}
}
}
private class InviteeListener implements EventListener {
volatile boolean requestReceived = false;
volatile boolean responseReceived = false;
private final boolean accept, answer;
InviteeListener(boolean accept, boolean answer) {
this.accept = accept;
this.answer = answer;
}
InviteeListener(boolean accept) {
this(accept, true);
}
@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) {
BlogInvitationReceivedEvent event =
(BlogInvitationReceivedEvent) e;
requestReceived = true;
if (!answer) return;
Blog b = event.getBlog();
try {
eventWaiter.assertEquals(1,
blogSharingManager1.getInvitations().size());
Contact c =
contactManager1.getContact(event.getContactId());
blogSharingManager1.respondToInvitation(b, c, accept);
} catch (DbException ex) {
eventWaiter.rethrow(ex);
} finally {
eventWaiter.resume();
}
}
// this is only needed for tests where a blog is re-shared
else if (e instanceof BlogInvitationResponseReceivedEvent) {
BlogInvitationResponseReceivedEvent event =
(BlogInvitationResponseReceivedEvent) e;
eventWaiter.assertEquals(contactId01, 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();
lifecycleManager1.startServices();
lifecycleManager2.startServices();
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 {
addDefaultIdentities();
addDefaultContacts();
getPersonalBlogOfSharer();
listenToEvents(accept);
}
private void addDefaultIdentities() throws DbException {
KeyPair keyPair = cryptoComponent.generateSignatureKeyPair();
author0 = authorFactory.createLocalAuthor(SHARER,
keyPair.getPublic().getEncoded(),
keyPair.getPrivate().getEncoded());
identityManager0.addLocalAuthor(author0);
keyPair = cryptoComponent.generateSignatureKeyPair();
author1 = authorFactory.createLocalAuthor(INVITEE,
keyPair.getPublic().getEncoded(),
keyPair.getPrivate().getEncoded());
identityManager1.addLocalAuthor(author1);
keyPair = cryptoComponent.generateSignatureKeyPair();
author2 = authorFactory.createLocalAuthor(CONTACT2,
keyPair.getPublic().getEncoded(),
keyPair.getPrivate().getEncoded());
identityManager2.addLocalAuthor(author2);
}
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
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);
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) {
listener0 = new SharerListener();
t0.getEventBus().addListener(listener0);
listener1 = new InviteeListener(accept);
t1.getEventBus().addListener(listener1);
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());
}
}

View File

@@ -1,100 +0,0 @@
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.PrivateGroupFactory;
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.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.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
})
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();
SyncSessionFactory getSyncSessionFactory();
/* the following methods are only needed to manually construct messages */
DatabaseComponent getDatabaseComponent();
PrivateGroupFactory getPrivateGroupFactory();
ClientHelper getClientHelper();
MessageQueueManager getMessageQueueManager();
}

View File

@@ -1,446 +0,0 @@
package org.briarproject;
import junit.framework.Assert;
import net.jodah.concurrentunit.Waiter;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.contact.ContactManager;
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.briarproject.util.StringUtils;
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.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
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;
public class ForumManagerTest {
private LifecycleManager lifecycleManager0, lifecycleManager1;
private SyncSessionFactory sync0, sync1;
private ForumManager forumManager0, forumManager1;
private ContactManager contactManager0, contactManager1;
private ContactId contactId0,contactId1;
private IdentityManager identityManager0, identityManager1;
private LocalAuthor author0, author1;
private Forum forum0;
@Inject
Clock clock;
@Inject
AuthorFactory authorFactory;
@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;
@Before
public void setUp() throws Exception {
ForumManagerTestComponent component =
DaggerForumManagerTestComponent.builder().build();
component.inject(this);
injectEagerSingletons(component);
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);
identityManager0 = t0.getIdentityManager();
identityManager1 = t1.getIdentityManager();
contactManager0 = t0.getContactManager();
contactManager1 = t1.getContactManager();
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();
}
private ForumPost createForumPost(GroupId groupId, ForumPost parent,
String body, long ms) throws Exception {
return forumPostFactory.createAnonymousPost(groupId, ms,
parent == null ? null : parent.getMessage().getId(),
"text/plain", StringUtils.toUtf8(body));
}
@Test
public void testForumPost() throws Exception {
startLifecycles();
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);
assertEquals(ms1, post1.getMessage().getTimestamp());
ForumPost post2 =
createForumPost(forum.getGroup().getId(), post1, body2, ms2);
assertEquals(ms2, post2.getMessage().getTimestamp());
forumManager0.addLocalPost(post1);
forumManager0.setReadFlag(post1.getMessage().getId(), true);
forumManager0.addLocalPost(post2);
forumManager0.setReadFlag(post2.getMessage().getId(), false);
Collection<ForumPostHeader> headers =
forumManager0.getPostHeaders(forum.getGroup().getId());
assertEquals(2, headers.size());
for (ForumPostHeader h : headers) {
final String hBody =
StringUtils.fromUtf8(forumManager0.getPostBody(h.getId()));
boolean isPost1 = h.getId().equals(post1.getMessage().getId());
boolean isPost2 = h.getId().equals(post2.getMessage().getId());
Assert.assertTrue(isPost1 || isPost2);
if (isPost1) {
assertEquals(h.getTimestamp(), ms1);
assertEquals(body1, hBody);
assertNull(h.getParentId());
assertTrue(h.isRead());
}
else {
assertEquals(h.getTimestamp(), ms2);
assertEquals(body2, hBody);
assertEquals(h.getParentId(), post2.getParent());
assertFalse(h.isRead());
}
}
forumManager0.removeForum(forum);
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);
forumManager0.addLocalPost(post1);
assertEquals(1, forumManager0.getPostHeaders(g).size());
assertEquals(0, forumManager1.getPostHeaders(g).size());
// send post to 1
sync0To1();
deliveryWaiter.await(TIMEOUT, 1);
assertEquals(1, forumManager1.getPostHeaders(g).size());
// add another forum post
time = clock.currentTimeMillis();
ForumPost post2 = createForumPost(g, null, "b", time);
forumManager1.addLocalPost(post2);
assertEquals(1, forumManager0.getPostHeaders(g).size());
assertEquals(2, forumManager1.getPostHeaders(g).size());
// send post to 0
sync1To0();
deliveryWaiter.await(TIMEOUT, 1);
assertEquals(2, forumManager1.getPostHeaders(g).size());
stopLifecycles();
}
@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);
forumManager0.addLocalPost(post2);
assertEquals(1, forumManager0.getPostHeaders(g).size());
assertEquals(0, forumManager1.getPostHeaders(g).size());
// send post to 1 without waiting for message delivery
sync0To1();
validationWaiter.await(TIMEOUT, 1);
assertEquals(0, forumManager1.getPostHeaders(g).size());
// now add the parent post as well
forumManager0.addLocalPost(post1);
assertEquals(2, forumManager0.getPostHeaders(g).size());
assertEquals(0, forumManager1.getPostHeaders(g).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();
}
@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);
// 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);
forumManager0.addLocalPost(post);
assertEquals(1, forumManager0.getPostHeaders(g).size());
assertEquals(0, forumManager1.getPostHeaders(g).size());
// send the child post to 1
sync0To1();
validationWaiter.await(TIMEOUT, 1);
assertEquals(1, forumManager0.getPostHeaders(g).size());
assertEquals(0, forumManager1.getPostHeaders(g).size());
// now also add the parent post which is in another group
forumManager0.addLocalPost(post1);
assertEquals(1, forumManager0.getPostHeaders(g1).size());
assertEquals(0, forumManager1.getPostHeaders(g1).size());
// send posts to 1
sync0To1();
deliveryWaiter.await(TIMEOUT, 1);
assertEquals(1, forumManager0.getPostHeaders(g).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(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 {
addDefaultIdentities();
addDefaultContacts();
addForum();
listenToEvents();
}
private void addDefaultIdentities() throws DbException {
author0 = authorFactory.createLocalAuthor(SHARER,
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
TestUtils.getRandomBytes(123));
identityManager0.addLocalAuthor(author0);
author1 = authorFactory.createLocalAuthor(INVITEE,
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
TestUtils.getRandomBytes(123));
identityManager1.addLocalAuthor(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 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();
lifecycleManager1.startServices();
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());
}
}

View File

@@ -1,85 +0,0 @@
package org.briarproject;
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.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
})
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();
ForumSharingManager getForumSharingManager();
ForumManager getForumManager();
SyncSessionFactory getSyncSessionFactory();
}

View File

@@ -2,17 +2,12 @@ package org.briarproject;
import net.jodah.concurrentunit.Waiter;
import org.briarproject.api.Bytes;
import org.briarproject.api.clients.MessageQueueManager;
import org.briarproject.api.clients.PrivateGroupFactory;
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.KeyParser;
import org.briarproject.api.crypto.PrivateKey;
import org.briarproject.api.crypto.SecretKey;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.db.DatabaseComponent;
@@ -23,32 +18,24 @@ 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.event.MessageValidatedEvent;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.forum.ForumInvitationRequest;
import org.briarproject.api.forum.ForumInvitationResponse;
import org.briarproject.api.forum.ForumInvitationMessage;
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.InvitationItem;
import org.briarproject.api.sharing.InvitationMessage;
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;
@@ -71,34 +58,29 @@ 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.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.briarproject.api.forum.ForumConstants.SHARE_MSG_TYPE_INVITATION;
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class ForumSharingIntegrationTest extends BriarTestCase {
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;
LifecycleManager lifecycleManager0, lifecycleManager1, lifecycleManager2;
SyncSessionFactory sync0, sync1, sync2;
ForumManager forumManager0, forumManager1, forumManager2;
ContactManager contactManager0, contactManager1, contactManager2;
ContactId contactId0, contactId2, contactId1, contactId21;
IdentityManager identityManager0, identityManager1, identityManager2;
LocalAuthor author0, author1, author2;
Forum forum0;
SharerListener listener0, listener2;
InviteeListener listener1;
@Inject
Clock clock;
@Inject
AuthorFactory authorFactory;
@Inject
ForumPostFactory forumPostFactory;
@Inject
CryptoComponent cryptoComponent;
// objects accessed from background threads need to be volatile
private volatile ForumSharingManager forumSharingManager0;
@@ -113,7 +95,6 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
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());
@@ -152,6 +133,7 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
contactManager2 = t2.getContactManager();
forumManager0 = t0.getForumManager();
forumManager1 = t1.getForumManager();
forumManager2 = t2.getForumManager();
forumSharingManager0 = t0.getForumSharingManager();
forumSharingManager1 = t1.getForumSharingManager();
forumSharingManager2 = t2.getForumSharingManager();
@@ -173,7 +155,7 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1, "Hi!");
.sendForumInvitation(forum0.getId(), contactId1, "Hi!");
// sync first request message
syncToInvitee();
@@ -186,34 +168,23 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
assertTrue(listener0.responseReceived);
// forum was added successfully
assertEquals(0, forumSharingManager0.getInvitations().size());
assertEquals(0, forumSharingManager0.getAvailableForums().size());
assertEquals(1, forumManager1.getForums().size());
// invitee has one invitation message from sharer
List<InvitationMessage> list =
List<ForumInvitationMessage> list =
new ArrayList<>(forumSharingManager1
.getInvitationMessages(contactId0));
assertEquals(2, list.size());
.getForumInvitationMessages(contactId0));
assertEquals(1, 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());
}
}
// sharer has own invitation message and response
assertEquals(2,
forumSharingManager0.getInvitationMessages(contactId1)
ForumInvitationMessage invitation = list.get(0);
assertFalse(invitation.isAvailable());
assertEquals(forum0.getName(), invitation.getForumName());
assertEquals(contactId1, invitation.getContactId());
assertEquals("Hi!", invitation.getMessage());
// sharer has own invitation message
assertEquals(1,
forumSharingManager0.getForumInvitationMessages(contactId1)
.size());
// forum can not be shared again
Contact c1 = contactManager0.getContact(contactId1);
@@ -234,7 +205,7 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1, null);
.sendForumInvitation(forum0.getId(), contactId1, null);
// sync first request message
syncToInvitee();
@@ -247,36 +218,25 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
assertTrue(listener0.responseReceived);
// forum was not added
assertEquals(0, forumSharingManager0.getInvitations().size());
assertEquals(0, forumSharingManager0.getAvailableForums().size());
assertEquals(0, forumManager1.getForums().size());
// forum is no longer available to invitee who declined
assertEquals(0, forumSharingManager1.getInvitations().size());
assertEquals(0, forumSharingManager1.getAvailableForums().size());
// invitee has one invitation message from sharer and one response
List<InvitationMessage> list =
// invitee has one invitation message from sharer
List<ForumInvitationMessage> 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());
}
}
// sharer has own invitation message and response
assertEquals(2,
forumSharingManager0.getInvitationMessages(contactId1)
.getForumInvitationMessages(contactId0));
assertEquals(1, list.size());
// check other things are alright with the forum message
ForumInvitationMessage invitation = list.get(0);
assertFalse(invitation.isAvailable());
assertEquals(forum0.getName(), invitation.getForumName());
assertEquals(contactId1, invitation.getContactId());
assertEquals(null, invitation.getMessage());
// sharer has own invitation message
assertEquals(1,
forumSharingManager0.getForumInvitationMessages(contactId1)
.size());
// forum can be shared again
Contact c1 = contactManager0.getContact(contactId1);
@@ -295,7 +255,7 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1, "Hi!");
.sendForumInvitation(forum0.getId(), contactId1, "Hi!");
// sync first request message
syncToInvitee();
@@ -308,7 +268,7 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
assertTrue(listener0.responseReceived);
// forum was added successfully
assertEquals(0, forumSharingManager0.getInvitations().size());
assertEquals(0, forumSharingManager0.getAvailableForums().size());
assertEquals(1, forumManager1.getForums().size());
assertTrue(forumManager1.getForums().contains(forum0));
@@ -328,7 +288,7 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
syncToSharer();
// forum is gone
assertEquals(0, forumSharingManager0.getInvitations().size());
assertEquals(0, forumSharingManager0.getAvailableForums().size());
assertEquals(0, forumManager1.getForums().size());
// sharer no longer shares forum with invitee
@@ -355,7 +315,7 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1, null);
.sendForumInvitation(forum0.getId(), contactId1, null);
// sync first request message
syncToInvitee();
@@ -368,7 +328,7 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
assertTrue(listener0.responseReceived);
// forum was added successfully
assertEquals(0, forumSharingManager0.getInvitations().size());
assertEquals(0, forumSharingManager0.getAvailableForums().size());
assertEquals(1, forumManager1.getForums().size());
assertTrue(forumManager1.getForums().contains(forum0));
@@ -409,53 +369,26 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
public void testSharerLeavesBeforeResponse() throws Exception {
startLifecycles();
try {
// initialize except event listeners
// initialize and let invitee accept all requests
defaultInit(true);
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1, null);
.sendForumInvitation(forum0.getId(), contactId1, null);
// sharer un-subscribes from forum
forumManager0.removeForum(forum0);
// prevent invitee response before syncing messages
respond = false;
// from her on expect the response to fail with a DbException
thrown.expect(DbException.class);
// sync first request message and leave message
syncToInvitee();
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.requestReceived);
// wait also for second message to arrive
msgWaiter.await(TIMEOUT, 1);
// 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;
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1, null);
// sharer un-subscribes from forum
forumManager0.removeForum(forum0);
// sync first request message and leave message
syncToInvitee();
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.requestReceived);
// wait also for second message to arrive
msgWaiter.await(TIMEOUT, 1);
// ensure that invitee has no forum invitations available
assertEquals(0, forumSharingManager1.getInvitations().size());
assertEquals(1, forumManager1.getForums().size());
// invitee has no forums available
assertEquals(0, forumSharingManager1.getAvailableForums().size());
} finally {
stopLifecycles();
}
@@ -470,7 +403,7 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1, "Hi!");
.sendForumInvitation(forum0.getId(), contactId1, "Hi!");
// sync first request message
syncToInvitee();
@@ -489,13 +422,12 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
listener1.requestReceived = false;
// get SessionId from invitation
List<InvitationMessage> list = new ArrayList<>(
List<ForumInvitationMessage> list = new ArrayList<>(
forumSharingManager1
.getInvitationMessages(contactId0));
assertEquals(2, list.size());
InvitationMessage msg = list.get(0);
.getForumInvitationMessages(contactId0));
assertEquals(1, list.size());
ForumInvitationMessage 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();
@@ -539,7 +471,7 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1, "Hi!");
.sendForumInvitation(forum0.getId(), contactId1, "Hi!");
// sync first request message
syncToInvitee();
@@ -553,12 +485,9 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
// 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(),
forumSharingManager1.sendForumInvitation(forum0.getId(),
contactId0,
"I am re-sharing this forum with you.");
@@ -567,79 +496,9 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
// make sure that no new request was received
assertFalse(listener0.requestReceived);
assertEquals(2,
forumSharingManager0.getInvitationMessages(contactId1)
assertEquals(1,
forumSharingManager0.getForumInvitationMessages(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());
txn.setComplete();
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);
}
// sync second invitation
alice = key0.compareTo(key1) < 0;
syncToSharer();
if (alice) {
assertFalse(listener0.requestReceived);
// sharer did not receive request, but response to own request
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.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();
}
@@ -654,7 +513,7 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1, "Hi!");
.sendForumInvitation(forum0.getId(), contactId1, "Hi!");
// sync first request message
syncToInvitee();
@@ -672,13 +531,12 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
forumSharingManager0.getSharedWith(forum0.getId()).size());
// remember SessionId from invitation
List<InvitationMessage> list = new ArrayList<>(
List<ForumInvitationMessage> list = new ArrayList<>(
forumSharingManager1
.getInvitationMessages(contactId0));
assertEquals(2, list.size());
InvitationMessage msg = list.get(0);
.getForumInvitationMessages(contactId0));
assertEquals(1, list.size());
ForumInvitationMessage msg = list.get(0);
SessionId sessionId = msg.getSessionId();
assertEquals(sessionId, list.get(1).getSessionId());
// contacts now remove each other
contactManager0.removeContact(contactId1);
@@ -756,25 +614,21 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
// send invitation
forumSharingManager0
.sendInvitation(forum0.getId(), contactId1, "Hi!");
.sendForumInvitation(forum0.getId(), contactId1, "Hi!");
// sync first request message
syncToInvitee();
// second sharer sends invitation for same forum
forumSharingManager2
.sendInvitation(forum0.getId(), contactId1, null);
.sendForumInvitation(forum0.getId(), contactId1, null);
// sync second request message
deliverMessage(sync2, contactId2, sync1, contactId1,
"Sharer2 to Invitee");
// make sure we now have two invitations to the same forum available
Collection<InvitationItem> forums =
forumSharingManager1.getInvitations();
// make sure we have only one forum available
Collection<Forum> forums =
forumSharingManager1.getAvailableForums();
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 =
@@ -803,119 +657,6 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
}
}
@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();
byte[] body = TestUtils.getRandomBytes(42);
KeyParser keyParser = cryptoComponent.getSignatureKeyParser();
PrivateKey key = keyParser.parsePrivateKey(author0.getPrivateKey());
ForumPost p = forumPostFactory
.createPseudonymousPost(forum0.getId(), time, null, author0,
"text/plain", body, key);
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.getRandomBytes(42);
key = keyParser.parsePrivateKey(author1.getPrivateKey());
p = forumPostFactory
.createPseudonymousPost(forum0.getId(), time, null, author1,
"text/plain", body, key);
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());
}
}
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);
// sync response back
syncToSharer();
eventWaiter.await(TIMEOUT, 1);
// now invitee creates a post
time = clock.currentTimeMillis();
body = TestUtils.getRandomBytes(42);
key = keyParser.parsePrivateKey(author1.getPrivateKey());
p = forumPostFactory
.createPseudonymousPost(forum0.getId(), time, null, author1,
"text/plain", body, key);
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());
}
}
assertTrue(found);
} finally {
stopLifecycles();
}
}
@After
public void tearDown() throws InterruptedException {
@@ -924,16 +665,18 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
private class SharerListener implements EventListener {
volatile boolean requestReceived = false;
volatile boolean responseReceived = false;
public volatile boolean requestReceived = false;
public volatile boolean responseReceived = false;
@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");
if (e instanceof MessageValidatedEvent) {
MessageValidatedEvent event = (MessageValidatedEvent) e;
if (event.getClientId()
.equals(forumSharingManager0.getClientId()) &&
!event.isLocal()) {
LOG.info("TEST: Sharer received message in group " +
((MessageValidatedEvent) e).getMessage()
.getGroupId().hashCode());
msgWaiter.resume();
}
} else if (e instanceof ForumInvitationResponseReceivedEvent) {
@@ -964,8 +707,8 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
private class InviteeListener implements EventListener {
volatile boolean requestReceived = false;
volatile boolean responseReceived = false;
public volatile boolean requestReceived = false;
public volatile boolean responseReceived = false;
private final boolean accept, answer;
@@ -978,13 +721,15 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
this(accept, true);
}
@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");
if (e instanceof MessageValidatedEvent) {
MessageValidatedEvent event = (MessageValidatedEvent) e;
if (event.getClientId()
.equals(forumSharingManager1.getClientId()) &&
!event.isLocal()) {
LOG.info("TEST: Invitee received message in group " +
((MessageValidatedEvent) e).getMessage()
.getGroupId().hashCode());
msgWaiter.resume();
}
} else if (e instanceof ForumInvitationReceivedEvent) {
@@ -994,17 +739,9 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
if (!answer) return;
Forum f = event.getForum();
try {
eventWaiter.assertEquals(1,
forumSharingManager1.getInvitations().size());
InvitationItem invitation =
forumSharingManager1.getInvitations().iterator()
.next();
eventWaiter.assertEquals(f, invitation.getShareable());
if (respond) {
Contact c =
contactManager1.getContact(event.getContactId());
forumSharingManager1.respondToInvitation(f, c, accept);
}
} catch (DbException ex) {
eventWaiter.rethrow(ex);
} finally {
@@ -1053,22 +790,17 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
}
private void addDefaultIdentities() throws DbException {
KeyPair keyPair = cryptoComponent.generateSignatureKeyPair();
author0 = authorFactory.createLocalAuthor(SHARER,
keyPair.getPublic().getEncoded(),
keyPair.getPrivate().getEncoded());
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
TestUtils.getRandomBytes(123));
identityManager0.addLocalAuthor(author0);
keyPair = cryptoComponent.generateSignatureKeyPair();
author1 = authorFactory.createLocalAuthor(INVITEE,
keyPair.getPublic().getEncoded(),
keyPair.getPrivate().getEncoded());
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
TestUtils.getRandomBytes(123));
identityManager1.addLocalAuthor(author1);
keyPair = cryptoComponent.generateSignatureKeyPair();
author2 = authorFactory.createLocalAuthor(SHARER2,
keyPair.getPublic().getEncoded(),
keyPair.getPrivate().getEncoded());
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
TestUtils.getRandomBytes(123));
identityManager2.addLocalAuthor(author2);
}
@@ -1076,21 +808,21 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
// sharer adds invitee as contact
contactId1 = contactManager0.addContact(author1,
author0.getId(), master, clock.currentTimeMillis(), true,
true, true
true
);
// second sharer does the same
contactId21 = contactManager2.addContact(author1,
author2.getId(), master, clock.currentTimeMillis(), true,
true, true
true
);
// invitee adds sharers back
contactId0 = contactManager1.addContact(author0,
author1.getId(), master, clock.currentTimeMillis(), true,
true, true
true
);
contactId2 = contactManager1.addContact(author2,
author1.getId(), master, clock.currentTimeMillis(), true,
true, true
true
);
}
@@ -1151,7 +883,6 @@ public class ForumSharingIntegrationTest extends BriarTestCase {
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());
}

View File

@@ -11,7 +11,6 @@ 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;
@@ -22,7 +21,6 @@ import org.briarproject.forum.ForumModule;
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;
@@ -43,16 +41,14 @@ import dagger.Component;
DatabaseModule.class,
EventModule.class,
ForumModule.class,
BlogsModule.class,
IdentityModule.class,
LifecycleModule.class,
PropertiesModule.class,
SharingModule.class,
SyncModule.class,
SystemModule.class,
TransportModule.class
})
interface ForumSharingIntegrationTestComponent {
public interface ForumSharingIntegrationTestComponent {
void inject(ForumSharingIntegrationTest testCase);
@@ -66,8 +62,6 @@ interface ForumSharingIntegrationTestComponent {
void inject(PropertiesModule.EagerSingletons init);
void inject(SharingModule.EagerSingletons init);
void inject(SyncModule.EagerSingletons init);
void inject(TransportModule.EagerSingletons init);

View File

@@ -1,17 +1,11 @@
package org.briarproject;
import android.support.annotation.Nullable;
import net.jodah.concurrentunit.Waiter;
import org.briarproject.api.FormatException;
import org.briarproject.api.clients.ClientHelper;
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;
@@ -25,11 +19,10 @@ 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.event.MessageValidatedEvent;
import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.introduction.IntroducerProtocolState;
import org.briarproject.api.introduction.IntroductionManager;
import org.briarproject.api.introduction.IntroductionMessage;
import org.briarproject.api.introduction.IntroductionRequest;
@@ -37,11 +30,9 @@ 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;
@@ -62,7 +53,6 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -73,42 +63,30 @@ import javax.inject.Inject;
import static org.briarproject.TestPluginsModule.MAX_LATENCY;
import static org.briarproject.TestPluginsModule.TRANSPORT_ID;
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.GROUP_ID;
import static org.briarproject.api.introduction.IntroductionConstants.NAME;
import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
import static org.briarproject.api.introduction.IntroductionConstants.STATE;
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.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class IntroductionIntegrationTest extends BriarTestCase {
private LifecycleManager lifecycleManager0, lifecycleManager1,
lifecycleManager2;
private SyncSessionFactory sync0, sync1, sync2;
private ContactManager contactManager0, contactManager1, contactManager2;
private ContactId contactId0, contactId1, contactId2;
private IdentityManager identityManager0, identityManager1,
identityManager2;
private LocalAuthor author0, author1, author2;
LifecycleManager lifecycleManager0, lifecycleManager1, lifecycleManager2;
SyncSessionFactory sync0, sync1, sync2;
ContactManager contactManager0, contactManager1, contactManager2;
ContactId contactId0, contactId1, contactId2;
IdentityManager identityManager0, identityManager1, identityManager2;
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;
@@ -172,13 +150,32 @@ public class IntroductionIntegrationTest extends BriarTestCase {
public void testIntroductionSession() throws Exception {
startLifecycles();
try {
// Add Identities And Contacts
// Add Identities
addDefaultIdentities();
addDefaultContacts();
// Add Transport Properties
addTransportProperties();
// Add introducees as contacts
contactId1 = contactManager0.addContact(author1,
author0.getId(), master, clock.currentTimeMillis(), true,
true
);
contactId2 = contactManager0.addContact(author2,
author0.getId(), master, clock.currentTimeMillis(), true,
true
);
// Add introducer back
contactId0 = contactManager1.addContact(author0,
author1.getId(), master, clock.currentTimeMillis(), true,
true
);
ContactId contactId02 = contactManager2.addContact(author0,
author2.getId(), master, clock.currentTimeMillis(), true,
true
);
assertTrue(contactId0.equals(contactId02));
// listen to events
IntroducerListener listener0 = new IntroducerListener();
t0.getEventBus().addListener(listener0);
@@ -236,18 +233,6 @@ public class IntroductionIntegrationTest extends BriarTestCase {
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());
}
}
assertDefaultUiMessages();
} finally {
stopLifecycles();
@@ -258,13 +243,29 @@ public class IntroductionIntegrationTest extends BriarTestCase {
public void testIntroductionSessionFirstDecline() throws Exception {
startLifecycles();
try {
// Add Identities And Contacts
// Add Identities
addDefaultIdentities();
addDefaultContacts();
// Add Transport Properties
addTransportProperties();
// Add introducees as contacts
contactId1 = contactManager0.addContact(author1, author0.getId(),
master, clock.currentTimeMillis(), true, true
);
contactId2 = contactManager0.addContact(author2, author0.getId(),
master, clock.currentTimeMillis(), true, true
);
// Add introducer back
contactId0 = contactManager1.addContact(author0, author1.getId(),
master, clock.currentTimeMillis(), true, true
);
ContactId contactId02 = contactManager2.addContact(author0,
author2.getId(), master, clock.currentTimeMillis(), true,
true
);
assertTrue(contactId0.equals(contactId02));
// listen to events
IntroducerListener listener0 = new IntroducerListener();
t0.getEventBus().addListener(listener0);
@@ -300,7 +301,7 @@ public class IntroductionIntegrationTest extends BriarTestCase {
assertTrue(listener0.response2Received);
// sync first forwarded response
deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2");
deliverMessage(sync0, contactId0, sync2, contactId2);
// note how the introducer does not forward the second response,
// because after the first decline the protocol finished
@@ -335,13 +336,29 @@ public class IntroductionIntegrationTest extends BriarTestCase {
public void testIntroductionSessionSecondDecline() throws Exception {
startLifecycles();
try {
// Add Identities And Contacts
// Add Identities
addDefaultIdentities();
addDefaultContacts();
// Add Transport Properties
addTransportProperties();
// Add introducees as contacts
contactId1 = contactManager0.addContact(author1, author0.getId(),
master, clock.currentTimeMillis(), true, true
);
contactId2 = contactManager0.addContact(author2, author0.getId(),
master, clock.currentTimeMillis(), true, true
);
// Add introducer back
contactId0 = contactManager1.addContact(author0, author1.getId(),
master, clock.currentTimeMillis(), false, true
);
ContactId contactId02 = contactManager2.addContact(author0,
author2.getId(), master, clock.currentTimeMillis(), false,
true
);
assertTrue(contactId0.equals(contactId02));
// listen to events
IntroducerListener listener0 = new IntroducerListener();
t0.getEventBus().addListener(listener0);
@@ -407,13 +424,29 @@ public class IntroductionIntegrationTest extends BriarTestCase {
public void testIntroductionSessionDelayedFirstDecline() throws Exception {
startLifecycles();
try {
// Add Identities And Contacts
// Add Identities
addDefaultIdentities();
addDefaultContacts();
// Add Transport Properties
addTransportProperties();
// Add introducees as contacts
contactId1 = contactManager0.addContact(author1, author0.getId(),
master, clock.currentTimeMillis(), true, true
);
contactId2 = contactManager0.addContact(author2, author0.getId(),
master, clock.currentTimeMillis(), true, true
);
// Add introducer back
contactId0 = contactManager1.addContact(author0, author1.getId(),
master, clock.currentTimeMillis(), false, true
);
ContactId contactId02 = contactManager2.addContact(author0,
author2.getId(), master, clock.currentTimeMillis(), false,
true
);
assertTrue(contactId0.equals(contactId02));
// listen to events
IntroducerListener listener0 = new IntroducerListener();
t0.getEventBus().addListener(listener0);
@@ -470,13 +503,21 @@ public class IntroductionIntegrationTest extends BriarTestCase {
public void testIntroductionToSameContact() throws Exception {
startLifecycles();
try {
// Add Identities And Contacts
// Add Identities
addDefaultIdentities();
addDefaultContacts();
// Add Transport Properties
addTransportProperties();
// Add introducee as contact
contactId1 = contactManager0.addContact(author1, author0.getId(),
master, clock.currentTimeMillis(), true, true
);
// Add introducer back
contactId0 = contactManager1.addContact(author0, author1.getId(),
master, clock.currentTimeMillis(), true, true
);
// listen to events
IntroducerListener listener0 = new IntroducerListener();
t0.getEventBus().addListener(listener0);
@@ -527,21 +568,21 @@ public class IntroductionIntegrationTest extends BriarTestCase {
// Add introducees' authors as contacts
contactId1 = contactManager0.addContact(author1,
author0.getId(), master, clock.currentTimeMillis(), true,
true, true
true
);
contactId2 = contactManager0.addContact(author2,
author0.getId(), master, clock.currentTimeMillis(), true,
true, true
true
);
// Add introducer back
contactId0 = null;
ContactId contactId01 = contactManager1.addContact(author0,
author1.getId(), master, clock.currentTimeMillis(), false,
true, true
true
);
ContactId contactId02 = contactManager1.addContact(author0,
author2.getId(), master, clock.currentTimeMillis(), false,
true, true
true
);
// listen to events
@@ -612,13 +653,32 @@ public class IntroductionIntegrationTest extends BriarTestCase {
public void testSessionIdReuse() throws Exception {
startLifecycles();
try {
// Add Identities And Contacts
// Add Identities
addDefaultIdentities();
addDefaultContacts();
// Add Transport Properties
addTransportProperties();
// Add introducees as contacts
contactId1 = contactManager0.addContact(author1,
author0.getId(), master, clock.currentTimeMillis(), true,
true
);
contactId2 = contactManager0.addContact(author2,
author0.getId(), master, clock.currentTimeMillis(), true,
true
);
// Add introducer back
contactId0 = contactManager1.addContact(author0,
author1.getId(), master, clock.currentTimeMillis(), true,
true
);
ContactId contactId02 = contactManager2.addContact(author0,
author2.getId(), master, clock.currentTimeMillis(), true,
true
);
assertTrue(contactId0.equals(contactId02));
// listen to events
IntroducerListener listener0 = new IntroducerListener();
t0.getEventBus().addListener(listener0);
@@ -690,13 +750,32 @@ public class IntroductionIntegrationTest extends BriarTestCase {
public void testIntroducerRemovedCleanup() throws Exception {
startLifecycles();
try {
// Add Identities And Contacts
// Add Identities
addDefaultIdentities();
addDefaultContacts();
// Add Transport Properties
addTransportProperties();
// Add introducees as contacts
contactId1 = contactManager0.addContact(author1,
author0.getId(), master, clock.currentTimeMillis(), true,
true
);
contactId2 = contactManager0.addContact(author2,
author0.getId(), master, clock.currentTimeMillis(), true,
true
);
// Add introducer back
contactId0 = contactManager1.addContact(author0,
author1.getId(), master, clock.currentTimeMillis(), true,
true
);
ContactId contactId02 = contactManager2.addContact(author0,
author2.getId(), master, clock.currentTimeMillis(), true,
true
);
assertTrue(contactId0.equals(contactId02));
// listen to events
IntroducerListener listener0 = new IntroducerListener();
t0.getEventBus().addListener(listener0);
@@ -757,13 +836,32 @@ public class IntroductionIntegrationTest extends BriarTestCase {
public void testIntroduceesRemovedCleanup() throws Exception {
startLifecycles();
try {
// Add Identities And Contacts
// Add Identities
addDefaultIdentities();
addDefaultContacts();
// Add Transport Properties
addTransportProperties();
// Add introducees as contacts
contactId1 = contactManager0.addContact(author1,
author0.getId(), master, clock.currentTimeMillis(), true,
true
);
contactId2 = contactManager0.addContact(author2,
author0.getId(), master, clock.currentTimeMillis(), true,
true
);
// Add introducer back
contactId0 = contactManager1.addContact(author0,
author1.getId(), master, clock.currentTimeMillis(), true,
true
);
ContactId contactId02 = contactManager2.addContact(author0,
author2.getId(), master, clock.currentTimeMillis(), true,
true
);
assertTrue(contactId0.equals(contactId02));
// listen to events
IntroducerListener listener0 = new IntroducerListener();
t0.getEventBus().addListener(listener0);
@@ -834,133 +932,7 @@ public class IntroductionIntegrationTest extends BriarTestCase {
}
}
@Test
public void testModifiedResponse() throws Exception {
startLifecycles();
try {
addDefaultIdentities();
addDefaultContacts();
addTransportProperties();
// listen to events
IntroducerListener listener0 = new IntroducerListener();
t0.getEventBus().addListener(listener0);
IntroduceeListener listener1 = new IntroduceeListener(1, true);
t1.getEventBus().addListener(listener1);
IntroduceeListener listener2 = new IntroduceeListener(2, true);
t2.getEventBus().addListener(listener2);
// 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
MessageId responseId = null;
BdfDictionary response = null;
Group g2 = introductionGroupFactory
.createIntroductionGroup(introducee2);
ClientHelper clientHelper0 = t0.getClientHelper();
Map<MessageId, BdfDictionary> map =
clientHelper0.getMessageMetadataAsDictionary(g2.getId());
for (Map.Entry<MessageId, BdfDictionary> entry : map.entrySet()) {
if (entry.getValue().getLong(TYPE) == TYPE_RESPONSE) {
responseId = entry.getKey();
response = entry.getValue();
}
}
assertTrue(responseId != null && response != null);
// adapt outgoing message queue to removed message
decreaseOutgoingMessageCounter(clientHelper0, g2.getId(), 1);
// modify response by changing transport properties
BdfDictionary tp = response.getDictionary(TRANSPORT);
tp.put("fakeId", BdfDictionary.of(new BdfEntry("fake", "fake")));
response.put(TRANSPORT, tp);
// 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);
txn.setComplete();
} finally {
db0.endTransaction(txn);
}
// sync second response
deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0");
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 first ACK and its forward
deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0");
deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1");
// sync second ACK and forward it
deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0");
deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2");
// introducee2 should have detected the fake now
// and deleted introducee1 again
Collection<Contact> contacts2;
DatabaseComponent db2 = t2.getDatabaseComponent();
txn = db2.startTransaction(true);
try {
contacts2 = db2.getContacts(txn);
txn.setComplete();
} finally {
db2.endTransaction(txn);
}
assertEquals(1, contacts2.size());
// sync abort message to introducer
deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0");
// ensure introducer got the abort
SessionId sessionId = new SessionId(response.getRaw(SESSION_ID));
BdfDictionary state =
clientHelper0.getMessageMetadataAsDictionary(sessionId);
assertEquals(IntroducerProtocolState.ERROR.getValue(),
state.getLong(STATE).intValue());
// sync abort messages to introducees
deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1");
deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2");
// although aborted, introducee1 keeps the contact,
// so introducer can not make contacts disappear by sending abort
Collection<Contact> contacts1;
DatabaseComponent db1 = t1.getDatabaseComponent();
txn = db1.startTransaction(true);
try {
contacts1 = db1.getContacts(txn);
txn.setComplete();
} finally {
db1.endTransaction(txn);
}
assertEquals(2, contacts1.size());
} finally {
stopLifecycles();
}
}
// TODO add a test for faking responses when #256 is implemented
@After
public void tearDown() throws InterruptedException {
@@ -1003,48 +975,20 @@ public class IntroductionIntegrationTest extends BriarTestCase {
}
private void addDefaultIdentities() throws DbException {
KeyPair keyPair0 = crypto.generateSignatureKeyPair();
byte[] publicKey0 = keyPair0.getPublic().getEncoded();
byte[] privateKey0 = keyPair0.getPrivate().getEncoded();
author0 = authorFactory
.createLocalAuthor(INTRODUCER, publicKey0, privateKey0);
author0 = authorFactory.createLocalAuthor(INTRODUCER,
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
TestUtils.getRandomBytes(123));
identityManager0.addLocalAuthor(author0);
KeyPair keyPair1 = crypto.generateSignatureKeyPair();
byte[] publicKey1 = keyPair1.getPublic().getEncoded();
byte[] privateKey1 = keyPair1.getPrivate().getEncoded();
author1 = authorFactory
.createLocalAuthor(INTRODUCEE1, publicKey1, privateKey1);
author1 = authorFactory.createLocalAuthor(INTRODUCEE1,
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
TestUtils.getRandomBytes(123));
identityManager1.addLocalAuthor(author1);
KeyPair keyPair2 = crypto.generateSignatureKeyPair();
byte[] publicKey2 = keyPair2.getPublic().getEncoded();
byte[] privateKey2 = keyPair2.getPrivate().getEncoded();
author2 = authorFactory
.createLocalAuthor(INTRODUCEE2, publicKey2, privateKey2);
author2 = authorFactory.createLocalAuthor(INTRODUCEE2,
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
TestUtils.getRandomBytes(123));
identityManager2.addLocalAuthor(author2);
}
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)
throws IOException, TimeoutException {
@@ -1052,7 +996,7 @@ public class IntroductionIntegrationTest extends BriarTestCase {
}
private void deliverMessage(SyncSessionFactory fromSync, ContactId fromId,
SyncSessionFactory toSync, ContactId toId, @Nullable String debug)
SyncSessionFactory toSync, ContactId toId, String debug)
throws IOException, TimeoutException {
if (debug != null) LOG.info("TEST: Sending message from " + debug);
@@ -1089,26 +1033,29 @@ public class IntroductionIntegrationTest extends BriarTestCase {
private class IntroduceeListener implements EventListener {
private volatile boolean requestReceived = false;
private volatile boolean succeeded = false;
private volatile boolean aborted = false;
public volatile boolean requestReceived = false;
public volatile boolean succeeded = false;
public volatile boolean aborted = false;
private final int introducee;
private final boolean accept;
private IntroduceeListener(int introducee, boolean accept) {
IntroduceeListener(int introducee, boolean accept) {
this.introducee = introducee;
this.accept = accept;
}
@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()) {
if (e instanceof MessageValidatedEvent) {
MessageValidatedEvent event = (MessageValidatedEvent) e;
if (event.getClientId()
.equals(introductionManager0.getClientId()) &&
!event.isLocal()) {
LOG.info("TEST: Introducee" + introducee +
" received message");
" received message in group " +
((MessageValidatedEvent) e).getMessage()
.getGroupId().hashCode());
msgWaiter.resume();
}
} else if (e instanceof IntroductionRequestReceivedEvent) {
@@ -1142,7 +1089,6 @@ public class IntroductionIntegrationTest extends BriarTestCase {
}
}
} catch (DbException | IOException exception) {
msgWaiter.rethrow(exception);
eventWaiter.rethrow(exception);
} finally {
eventWaiter.resume();
@@ -1162,16 +1108,20 @@ public class IntroductionIntegrationTest extends BriarTestCase {
private class IntroducerListener implements EventListener {
private volatile boolean response1Received = false;
private volatile boolean response2Received = false;
private volatile boolean aborted = false;
public volatile boolean response1Received = false;
public volatile boolean response2Received = false;
public volatile boolean aborted = false;
@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");
if (e instanceof MessageValidatedEvent) {
MessageValidatedEvent event = (MessageValidatedEvent) e;
if (event.getClientId()
.equals(introductionManager0.getClientId()) &&
!event.isLocal()) {
LOG.info("TEST: Introducer received message in group " +
((MessageValidatedEvent) e).getMessage()
.getGroupId().hashCode());
msgWaiter.resume();
}
} else if (e instanceof IntroductionResponseReceivedEvent) {
@@ -1193,16 +1143,6 @@ public class IntroductionIntegrationTest extends BriarTestCase {
}
}
private void decreaseOutgoingMessageCounter(ClientHelper clientHelper,
GroupId g, int num) throws FormatException, DbException {
BdfDictionary gD = clientHelper.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);
}
private void injectEagerSingletons(
IntroductionIntegrationTestComponent component) {

View File

@@ -1,6 +1,5 @@
package org.briarproject;
import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.event.EventBus;
@@ -86,8 +85,6 @@ public interface IntroductionIntegrationTestComponent {
DatabaseComponent getDatabaseComponent();
ClientHelper getClientHelper();
MessageSender getMessageSender();
IntroductionGroupFactory getIntroductionGroupFactory();

View File

@@ -93,7 +93,7 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
Author bobAuthor = new Author(bobId, "Bob",
new byte[MAX_PUBLIC_KEY_LENGTH]);
ContactId contactId = contactManager.addContact(bobAuthor, aliceId,
master, timestamp, true, true, true);
master, timestamp, true, true);
// Send Bob a message
GroupId groupId = messagingManager.getConversationId(contactId);
@@ -146,7 +146,7 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
Author aliceAuthor = new Author(aliceId, "Alice",
new byte[MAX_PUBLIC_KEY_LENGTH]);
ContactId contactId = contactManager.addContact(aliceAuthor, bobId,
master, timestamp, false, true, true);
master, timestamp, false, true);
// Set up an event listener
MessageListener listener = new MessageListener();

View File

@@ -31,6 +31,7 @@ import java.util.Collection;
import javax.inject.Inject;
import static org.briarproject.api.sync.SyncConstants.MAX_GROUP_DESCRIPTOR_LENGTH;
import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -75,7 +76,7 @@ public class SyncIntegrationTest extends BriarTestCase {
streamNumber = 123;
// Create a group
ClientId clientId = new ClientId(TestUtils.getRandomId());
byte[] descriptor = new byte[0];
byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
Group group = groupFactory.createGroup(clientId, descriptor);
// Add two messages to the group
long timestamp = System.currentTimeMillis();

View File

@@ -1,11 +0,0 @@
[main]
host = https://www.transifex.com
lang_map = pt_BR: pt-rBR
[briar.stringsxml-5]
file_filter = res/values-<lang>/strings.xml
source_file = res/values/strings.xml
source_lang = en
type = ANDROID
minimum_perc = 25

View File

@@ -7,7 +7,8 @@
android:versionName="0.12">
<uses-sdk
android:minSdkVersion="14"
android:minSdkVersion="9"
android:targetSdkVersion="22"
tools:overrideLibrary="android.support.v14.preference"
/>
@@ -50,9 +51,7 @@
android:finishOnTaskLaunch="true"
android:label="@string/crash_report_title"
android:launchMode="singleInstance"
android:process=":briar_error_handler"
android:theme="@style/BriarThemeNoActionBar.Default"
android:windowSoftInputMode="stateHidden">
android:process=":briar_error_handler">
</activity>
<activity
@@ -68,8 +67,7 @@
<activity
android:name=".android.SetupActivity"
android:label="@string/setup_title"
android:windowSoftInputMode="adjustResize">
android:label="@string/setup_title">
</activity>
<activity
@@ -101,8 +99,8 @@
</activity>
<activity
android:name=".android.sharing.InvitationsForumActivity"
android:label="@string/forum_invitations_title"
android:name=".android.forum.AvailableForumsActivity"
android:label="@string/available_forums_title"
android:parentActivityName=".android.NavDrawerActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
@@ -110,16 +108,6 @@
/>
</activity>
<activity
android:name=".android.sharing.InvitationsBlogActivity"
android:label="@string/blogs_sharing_invitations_title"
android:parentActivityName=".android.contact.ConversationActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".android.contact.ConversationActivity"
/>
</activity>
<activity
android:name=".android.forum.CreateForumActivity"
android:label="@string/create_forum_title"
@@ -142,48 +130,8 @@
</activity>
<activity
android:name=".android.sharing.ShareForumActivity"
android:label="@string/activity_share_toolbar_header"
android:parentActivityName=".android.forum.ForumActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".android.forum.ForumActivity"
/>
</activity>
<activity
android:name=".android.sharing.ShareBlogActivity"
android:label="@string/activity_share_toolbar_header"
android:parentActivityName=".android.blogs.BlogActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".android.blogs.BlogActivity"
/>
</activity>
<activity
android:name=".android.sharing.SharingStatusForumActivity"
android:label="@string/sharing_status"
android:parentActivityName=".android.forum.ForumActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".android.forum.ForumActivity"
/>
</activity>
<activity
android:name=".android.sharing.SharingStatusBlogActivity"
android:label="@string/sharing_status"
android:parentActivityName=".android.blogs.BlogActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".android.blogs.BlogActivity"
/>
</activity>
<activity
android:name=".android.blogs.CreateBlogActivity"
android:label="@string/blogs_my_blogs_label"
android:name=".android.forum.ReadForumPostActivity"
android:label="@string/app_name"
android:parentActivityName=".android.NavDrawerActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
@@ -192,51 +140,30 @@
</activity>
<activity
android:name=".android.blogs.BlogActivity"
android:parentActivityName=".android.NavDrawerActivity">
android:name=".android.forum.ShareForumActivity"
android:label="@string/forums_share_toolbar_header"
android:parentActivityName=".android.forum.ForumActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".android.NavDrawerActivity"
android:value=".android.forum.ForumActivity"
/>
</activity>
<activity
android:name=".android.blogs.WriteBlogPostActivity"
android:label="@string/blogs_write_blog_post"
android:parentActivityName=".android.blogs.BlogActivity"
android:windowSoftInputMode="stateVisible|adjustResize">
android:name=".android.forum.ForumSharingStatusActivity"
android:label="@string/forum_sharing_status"
android:parentActivityName=".android.forum.ForumActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".android.blogs.BlogActivity"
android:value=".android.forum.ForumActivity"
/>
</activity>
<activity
android:name=".android.blogs.ReblogActivity"
android:label="@string/blogs_reblog_button"
android:parentActivityName=".android.blogs.BlogActivity"
android:windowSoftInputMode="stateHidden">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".android.blogs.BlogActivity"
/>
</activity>
<activity
android:name=".android.blogs.RssFeedImportActivity"
android:label="@string/blogs_rss_feeds_import"
android:name=".android.forum.WriteForumPostActivity"
android:label="@string/app_name"
android:parentActivityName=".android.NavDrawerActivity"
android:windowSoftInputMode="stateVisible|adjustResize">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".android.NavDrawerActivity"
/>
</activity>
<activity
android:name=".android.blogs.RssFeedManageActivity"
android:label="@string/blogs_rss_feeds_manage"
android:parentActivityName=".android.NavDrawerActivity">
android:windowSoftInputMode="stateVisible">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".android.NavDrawerActivity"
@@ -287,7 +214,7 @@
<activity
android:name=".android.SettingsActivity"
android:label="@string/settings_button"
android:label="@string/settings_title"
android:parentActivityName=".android.NavDrawerActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
@@ -299,16 +226,6 @@
</intent-filter>
</activity>
<activity
android:name=".android.ChangePasswordActivity"
android:label="@string/change_password"
android:parentActivityName=".android.SettingsActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".android.SettingsActivity"
/>
</activity>
<activity
android:name=".android.panic.PanicPreferencesActivity"
android:label="@string/panic_setting">

View File

@@ -1,92 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="49"
height="20"
viewBox="0 0 49.000004 20"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="trust-indicator.svg">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="15.839192"
inkscape:cx="19.828141"
inkscape:cy="4.1791031"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1920"
inkscape:window-height="993"
inkscape:window-x="1440"
inkscape:window-y="0"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-216.17711,-507.04154)">
<g
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25px;line-height:125%;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#b7b7b7;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="text4136"
transform="matrix(1,0,0,0.90497738,-18.96574,55.694085)">
<path
d="m 250.64285,514.07648 0,-2.275 -2.55,0 0,-3.8 2.55,0 0,-2.275 -2.55,0 0,-4.225 -2.375,0 0,4.225 -3.15,0 0,-4.225 -2.375,0 0,4.225 -2.55,0 0,2.275 2.55,0 0,3.8 -2.55,0 0,2.275 2.55,0 0,4 2.375,0 0,-4 3.15,0 0,4 2.375,0 0,-4 2.55,0 z m -4.925,-2.275 -3.15,0 0,-3.8 3.15,0 0,3.8 z"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:Titillium;-inkscape-font-specification:'Titillium Semi-Bold';fill:#b7b7b7;fill-opacity:1"
id="path4745"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1,0,0,0.90497738,-3.4657389,55.694085)"
id="g4755"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25px;line-height:125%;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#b7b7b7;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1">
<path
inkscape:connector-curvature="0"
id="path4757"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:Titillium;-inkscape-font-specification:'Titillium Semi-Bold';fill:#b7b7b7;fill-opacity:1"
d="m 250.64285,514.07648 0,-2.275 -2.55,0 0,-3.8 2.55,0 0,-2.275 -2.55,0 0,-4.225 -2.375,0 0,4.225 -3.15,0 0,-4.225 -2.375,0 0,4.225 -2.55,0 0,2.275 2.55,0 0,3.8 -2.55,0 0,2.275 2.55,0 0,4 2.375,0 0,-4 3.15,0 0,4 2.375,0 0,-4 2.55,0 z m -4.925,-2.275 -3.15,0 0,-3.8 3.15,0 0,3.8 z" />
</g>
<g
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:25px;line-height:125%;font-family:FreeSans;-inkscape-font-specification:FreeSans;letter-spacing:0px;word-spacing:0px;fill:#b7b7b7;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
id="g4139"
transform="matrix(1,0,0,0.90497738,12.034262,55.694085)">
<path
d="m 250.64285,514.07648 0,-2.275 -2.55,0 0,-3.8 2.55,0 0,-2.275 -2.55,0 0,-4.225 -2.375,0 0,4.225 -3.15,0 0,-4.225 -2.375,0 0,4.225 -2.55,0 0,2.275 2.55,0 0,3.8 -2.55,0 0,2.275 2.55,0 0,4 2.375,0 0,-4 3.15,0 0,4 2.375,0 0,-4 2.55,0 z m -4.925,-2.275 -3.15,0 0,-3.8 3.15,0 0,3.8 z"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:Titillium;-inkscape-font-specification:'Titillium Semi-Bold';fill:#b7b7b7;fill-opacity:1"
id="path4141"
inkscape:connector-curvature="0" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.6 KiB

View File

@@ -11,20 +11,25 @@ dependencies {
compile project(':briar-api')
compile project(':briar-core')
compile fileTree(dir: 'libs', include: '*.jar')
// This shouldn't be necessary; per section 23.4.4 of the Gradle docs:
// "file dependencies are included in transitive project dependencies within the same build".
compile files('../briar-core/libs/jsocks.jar')
compile "com.android.support:support-v4:$supportVersion"
compile("com.android.support:appcompat-v7:$supportVersion") {
exclude module: 'support-v4'
}
compile("com.android.support:preference-v7:$supportVersion") {
exclude module: 'support-v4'
}
compile("com.android.support:preference-v14:$supportVersion") {
exclude module: 'support-v4'
exclude module: 'preference-v7'
exclude module: 'recyclerview-v7'
}
compile("com.android.support:design:$supportVersion") {
exclude module: 'support-v4'
exclude module: 'recyclerview-v7'
}
compile "com.android.support:cardview-v7:$supportVersion"
compile('ch.acra:acra:4.8.5') {
exclude module: 'support-v4'
exclude module: 'support-annotations'
@@ -42,6 +47,11 @@ dependencies {
testCompile project(path: ':briar-tests')
testCompile 'org.robolectric:robolectric:3.0'
testCompile 'org.mockito:mockito-core:1.10.19'
androidTestCompile 'org.robolectric:robolectric:3.0'
androidTestCompile 'org.mockito:mockito-core:1.10.19'
androidTestApt 'com.google.dagger:dagger-compiler:2.0.2'
androidTestCompile 'junit:junit:4.12'
}
dependencyVerification {
@@ -53,13 +63,13 @@ dependencyVerification {
'com.google.zxing:core:b4d82452e7a6bf6ec2698904b332431717ed8f9a850224f295aec89de80f2259',
'com.android.support:support-v4:81ce890f26d35c75ad17d0f998a7e3230330c3b41e0b629566bc744bee89e448',
'com.android.support:appcompat-v7:00f9d93acacd6731f309724054bf51492814b4b2869f16d7d5c0038dcb8c9a0d',
'com.android.support:preference-v7:775101bd07bd052e455761c5c5d9523d7ad59f2f320e3e8cbde241fd6b1d6025',
'com.android.support:preference-v14:44881bb46094e86d0bc2426f205419674a5b4eb514b44b5a4659b5de29f71eb7',
'com.android.support:design:003e0c0bea0a6891f8b2bc43f20ae7af2a49a17363e5bb10df5ee0bae12fa686',
'com.android.support:support-annotations:786ab0d060774fb95cfdaf4878771e14b85733b1af9d72a4aae762dc7c1dff9f',
'com.android.support:animated-vector-drawable:06d1963b85aa917099d7757e6a7b3e4dc06889413dc747f625ae8683606db3a1',
'com.android.support:support-vector-drawable:799bafe4c3de812386f0b291f744d5d6876452722dd40189b9ab87dbbf594ea1',
'com.android.support:recyclerview-v7:44040a888e23e0c93162a3377cfe06751080e3c22d369ab0d4301ef60d63b0fe',
'com.android.support:cardview-v7:4595f1c4a28cfa083b6c0920ad4d49e1c2ca4b8302a955e548f68eb63b74931b',
]
}
@@ -67,10 +77,6 @@ android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
resValue "string", "app_package", "org.briarproject"
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
@@ -94,16 +100,24 @@ android {
unitTests.returnDefaultValues = true
}
}
// Move the build types to build-types/<type>
// For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
// This moves them out of them default location under src/<type>/... which would
// conflict with src/ being used by the main source set.
// Adding new build types or product flavors should be accompanied
// by a similar customization.
debug.setRoot('build-types/debug')
release.setRoot('build-types/release')
}
buildTypes {
debug {
shrinkResources false
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
release {
shrinkResources true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
@@ -115,10 +129,8 @@ android {
}
lintOptions {
warning 'MissingTranslation'
warning 'ImpliedQuantity'
abortOnError false
}
dexOptions {
incremental true
}

View File

@@ -4,16 +4,17 @@
-dontobfuscate
-verbose
-useuniqueclassmembernames
#-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
# For comfortability in case we do obfuscate
# -renamesourcefileattribute SourceFile
-keepattributes SourceFile, LineNumberTable, *Annotation*, Signature, InnerClasses, EnclosingMethod
-keepattributes SourceFile,LineNumberTable,*Annotation*,Signature, InnerClasses, EnclosingMethod
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class com.android.vending.licensing.ILicensingService
-keepclasseswithmembers class * { native <methods>; }
-keepclasseswithmembers class * {
public <init> (android.content.Context, android.util.AttributeSet);
@@ -31,32 +32,31 @@
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
-keepclassmembers class * {
@com.google.inject.Inject <init>(...);
@com.google.inject.Inject <fields>;
}
# Just in case Roboguice events are used
-keepclassmembers class * {
void *(**On*Event);
}
-keep class org.h2.** { *; }
-keep class org.briarproject.** { *; }
-keep class com.google.inject.** { *; }
-keep class javax.inject.** { *; }
-keep class javax.annotation.** { *; }
-keep class roboguice.** { *; }
-keep class dagger.** { *; }
-keep class com.google.zxing.Result
-keep class com.google.** { *; }
-dontwarn org.h2.**
-dontnote org.h2.**
-dontwarn net.sf.cglib.**
-dontwarn org.briarproject.plugins.tcp.**
-dontnote org.briarproject.crypto.**
-dontnote org.spongycastle.crypto.parsers.ECIESPublicKeyParser
-dontwarn roboguice.**
-dontwarn net.sourceforge.jsocks.**
-dontnote android.support.**
-dontnote dagger.**
-dontwarn dagger.**
-dontnote com.google.common.**
-dontwarn com.google.common.**
# RSS libraries
-keep class com.rometools.rome.feed.synd.impl.** { *;}
-keep class com.rometools.rome.io.impl.** { *;}
-dontnote com.rometools.rome.**
-dontwarn javax.xml.stream.**
-dontwarn org.jaxen.**
-dontwarn java.nio.**
-dontwarn org.codehaus.mojo.animal_sniffer.**
-dontwarn org.slf4j.impl.**
-dontwarn com.google.common.**

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 975 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1009 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 708 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 713 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1014 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
A FAB does not work, because even with fabSize="mini" it will be too big due to shadow drawing
on lower API levels
-->
<ripple
xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/briar_primary_dark">
<item>
<shape android:shape="oval">
<solid android:color="@color/briar_primary"/>
</shape>
</item>
</ripple>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 853 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Some files were not shown because too many files have changed in this diff Show More