implementing robolectric and mockito

This commit is contained in:
Ernir Erlingsson
2016-04-28 15:28:35 +02:00
parent aa3ef896f5
commit adb7d37f86
18 changed files with 1681 additions and 16 deletions

View File

@@ -8,6 +8,7 @@ apply plugin: 'de.undercouch.download'
repositories {
jcenter()
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
}
dependencies {
@@ -44,6 +45,18 @@ dependencies {
compile 'com.google.zxing:core:3.2.1'
apt 'com.google.dagger:dagger-compiler:2.0.2'
provided 'javax.annotation:jsr250-api:1.0'
testCompile 'junit:junit:4.12'
testCompile 'net.jodah:concurrentunit:0.4.2'
testApt 'com.google.dagger:dagger-compiler:2.4'
testCompile project(path: ':briar-tests')
testCompile 'org.robolectric:robolectric:3.1-SNAPSHOT'
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.4'
androidTestCompile 'junit:junit:4.12'
}
dependencyVerification {
@@ -81,7 +94,19 @@ android {
}
// Move the tests to tests/java, tests/res, etc...
instrumentTest.setRoot('tests')
//instrumentTest.setRoot('tests')
// unitTest.setRoot('tests')
androidTest.setRoot('androidTest')
androidTest {
java.srcDirs = ['androidTest/java']
}
test.setRoot('test')
test {
java.srcDirs = ['test/java']
}
// Move the build types to build-types/<type>
// For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...

View File

@@ -48,6 +48,9 @@
-keep class roboguice.** { *; }
-keep class dagger.** { *; }
-keep class com.google.** { *; }
-keep class javax.** { *; }
-keep class org.eclipse.** { *; }
-keep class com.squareup.** { *; }
-dontwarn org.h2.**
-dontnote org.h2.**

View File

@@ -54,34 +54,33 @@ public class ActivityModule {
@ActivityScope
@Provides
SetupController provideSetupController(
SetupControllerImp setupControllerImp) {
return setupControllerImp;
protected SetupController provideSetupController() {
return new SetupControllerImp();
}
@ActivityScope
@Provides
ConfigController provideConfigController(
protected ConfigController provideConfigController(
ConfigControllerImp configControllerImp) {
return configControllerImp;
}
@ActivityScope
@Provides
SharedPreferences provideSharedPreferences(Activity activity) {
protected SharedPreferences provideSharedPreferences(Activity activity) {
return activity.getSharedPreferences("db", Context.MODE_PRIVATE);
}
@ActivityScope
@Provides
PasswordController providePasswordController(
protected PasswordController providePasswordController(
PasswordControllerImp passwordControllerImp) {
return passwordControllerImp;
}
@ActivityScope
@Provides
BriarController provideBriarController(
protected BriarController provideBriarController(
BriarControllerImp briarControllerImp) {
activity.addLifecycleController(briarControllerImp);
return briarControllerImp;
@@ -89,7 +88,7 @@ public class ActivityModule {
@ActivityScope
@Provides
NavDrawerController provideNavDrawerController(
protected NavDrawerController provideNavDrawerController(
NavDrawerControllerImp navDrawerControllerImp) {
activity.addLifecycleController(navDrawerControllerImp);
if (activity instanceof TransportStateListener) {
@@ -101,7 +100,7 @@ public class ActivityModule {
@ActivityScope
@Provides
BriarServiceConnection provideBriarServiceConnection() {
protected BriarServiceConnection provideBriarServiceConnection() {
return new BriarServiceConnection();
}

View File

@@ -38,7 +38,7 @@ public abstract class BaseActivity extends AppCompatActivity {
activityComponent = DaggerActivityComponent.builder()
.androidComponent(applicationComponent)
.activityModule(new ActivityModule(this))
.activityModule(getActivityModule())
.build();
injectActivity(activityComponent);
@@ -48,6 +48,11 @@ public abstract class BaseActivity extends AppCompatActivity {
}
}
// This exists to make test overrides easier
protected ActivityModule getActivityModule() {
return new ActivityModule(this);
}
@Override
protected void onResume() {
super.onResume();

View File

@@ -27,8 +27,6 @@ import javax.inject.Inject;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static org.briarproject.android.TestingConstants.PREVENT_SCREENSHOTS;
import static org.briarproject.api.crypto.PasswordStrengthEstimator.WEAK;
import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
@@ -66,7 +64,7 @@ public class SetupActivity extends BaseActivity implements OnClickListener,
createAccountButton = (Button) findViewById(R.id.create_account);
progress = (ProgressBar) findViewById(R.id.progress_wheel);
if (PREVENT_SCREENSHOTS) getWindow().addFlags(FLAG_SECURE);
// if (PREVENT_SCREENSHOTS) getWindow().addFlags(FLAG_SECURE);
TextWatcher tw = new TextWatcher() {
@Override
@@ -125,6 +123,7 @@ public class SetupActivity extends BaseActivity implements OnClickListener,
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
hideSoftKeyboard(v);
return true;
}

View File

@@ -8,6 +8,7 @@ import android.provider.Settings;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.logging.Logger;
import javax.inject.Inject;
@@ -15,6 +16,9 @@ import static android.provider.Settings.Secure.ANDROID_ID;
class AndroidSeedProvider extends LinuxSeedProvider {
private static final Logger LOG =
Logger.getLogger(LinuxSeedProvider.class.getName());
private final Context appContext;
@Inject

View File

@@ -0,0 +1,859 @@
package briarproject;
import net.jodah.concurrentunit.Waiter;
import org.briarproject.BriarTestCase;
import org.briarproject.TestDatabaseModule;
import org.briarproject.TestUtils;
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.IntroductionAbortedEvent;
import org.briarproject.api.event.IntroductionRequestReceivedEvent;
import org.briarproject.api.event.IntroductionResponseReceivedEvent;
import org.briarproject.api.event.IntroductionSucceededEvent;
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.IntroductionManager;
import org.briarproject.api.introduction.IntroductionRequest;
import org.briarproject.api.introduction.SessionId;
import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.properties.TransportProperties;
import org.briarproject.api.properties.TransportPropertyManager;
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.introduction.IntroductionModule;
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.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.concurrent.TimeoutException;
import java.util.logging.Logger;
import javax.inject.Inject;
import static org.briarproject.TestPluginsModule.MAX_LATENCY;
import static org.briarproject.TestPluginsModule.TRANSPORT_ID;
import static org.briarproject.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 IntroductionIntegrationTest extends BriarTestCase {
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
AuthorFactory authorFactory;
// objects accessed from background threads need to be volatile
private volatile IntroductionManager introductionManager0;
private volatile IntroductionManager introductionManager1;
private volatile IntroductionManager introductionManager2;
private volatile Waiter eventWaiter;
private volatile Waiter msgWaiter;
private final File testDir = TestUtils.getTestDirectory();
private final SecretKey master = TestUtils.getSecretKey();
private final int TIMEOUT = 15000;
private final String INTRODUCER = "Introducer";
private final String INTRODUCEE1 = "Introducee1";
private final String INTRODUCEE2 = "Introducee2";
private static final Logger LOG =
Logger.getLogger(IntroductionIntegrationTest.class.getName());
private IntroductionIntegrationTestComponent t0, t1, t2;
@Before
public void setUp() {
IntroductionIntegrationTestComponent component =
DaggerIntroductionIntegrationTestComponent.builder().build();
component.inject(this);
injectEagerSingletons(component);
assertTrue(testDir.mkdirs());
File t0Dir = new File(testDir, INTRODUCER);
t0 = DaggerIntroductionIntegrationTestComponent.builder()
.testDatabaseModule(new TestDatabaseModule(t0Dir)).build();
injectEagerSingletons(t0);
File t1Dir = new File(testDir, INTRODUCEE1);
t1 = DaggerIntroductionIntegrationTestComponent.builder()
.testDatabaseModule(new TestDatabaseModule(t1Dir)).build();
injectEagerSingletons(t1);
File t2Dir = new File(testDir, INTRODUCEE2);
t2 = DaggerIntroductionIntegrationTestComponent.builder()
.testDatabaseModule(new TestDatabaseModule(t2Dir)).build();
injectEagerSingletons(t2);
identityManager0 = t0.getIdentityManager();
identityManager1 = t1.getIdentityManager();
identityManager2 = t2.getIdentityManager();
contactManager0 = t0.getContactManager();
contactManager1 = t1.getContactManager();
contactManager2 = t2.getContactManager();
introductionManager0 = t0.getIntroductionManager();
introductionManager1 = t1.getIntroductionManager();
introductionManager2 = t2.getIntroductionManager();
sync0 = t0.getSyncSessionFactory();
sync1 = t1.getSyncSessionFactory();
sync2 = t2.getSyncSessionFactory();
// initialize waiters fresh for each test
eventWaiter = new Waiter();
msgWaiter = new Waiter();
}
@Test
public void testIntroductionSession() throws Exception {
startLifecycles();
try {
// Add Identities
addDefaultIdentities();
// 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);
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 first request message
deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 1");
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener1.requestReceived);
// sync second request message
deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2");
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener2.requestReceived);
// sync first response
deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0");
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.response1Received);
// sync second response
deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0");
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.response2Received);
// sync 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(sync1, contactId1, sync0, contactId0, "1 to 0");
deliverMessage(sync0, contactId0, sync2, contactId2, "0 to 2");
// sync second ACK and its forward
deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0");
deliverMessage(sync0, contactId0, sync1, contactId1, "0 to 2");
// wait for introduction to succeed
eventWaiter.await(TIMEOUT, 2);
assertTrue(listener1.succeeded);
assertTrue(listener2.succeeded);
assertTrue(contactManager1
.contactExists(author2.getId(), author1.getId()));
assertTrue(contactManager2
.contactExists(author1.getId(), author2.getId()));
assertDefaultUiMessages();
} finally {
stopLifecycles();
}
}
@Test
public void testIntroductionSessionFirstDecline() throws Exception {
startLifecycles();
try {
// Add Identities
addDefaultIdentities();
// 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);
IntroduceeListener listener1 = new IntroduceeListener(1, false);
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, null, time);
// sync request messages
deliverMessage(sync0, contactId0, sync1, contactId1);
deliverMessage(sync0, contactId0, sync2, contactId2);
// wait for requests to arrive
eventWaiter.await(TIMEOUT, 2);
assertTrue(listener1.requestReceived);
assertTrue(listener2.requestReceived);
// sync first response
deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0");
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.response1Received);
// sync second response
deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0");
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.response2Received);
// sync first forwarded response
deliverMessage(sync0, contactId0, sync2, contactId2);
// note how the introducer does not forward the second response,
// because after the first decline the protocol finished
assertFalse(listener1.succeeded);
assertFalse(listener2.succeeded);
assertFalse(contactManager1
.contactExists(author2.getId(), author1.getId()));
assertFalse(contactManager2
.contactExists(author1.getId(), author2.getId()));
assertEquals(2,
introductionManager0.getIntroductionMessages(contactId1)
.size());
assertEquals(2,
introductionManager0.getIntroductionMessages(contactId2)
.size());
assertEquals(2,
introductionManager1.getIntroductionMessages(contactId0)
.size());
// introducee2 should also have the decline response of introducee1
assertEquals(3,
introductionManager2.getIntroductionMessages(contactId0)
.size());
} finally {
stopLifecycles();
}
}
@Test
public void testIntroductionSessionSecondDecline() throws Exception {
startLifecycles();
try {
// Add Identities
addDefaultIdentities();
// 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);
IntroduceeListener listener1 = new IntroduceeListener(1, true);
t1.getEventBus().addListener(listener1);
IntroduceeListener listener2 = new IntroduceeListener(2, false);
t2.getEventBus().addListener(listener2);
// make introduction
long time = clock.currentTimeMillis();
Contact introducee1 = contactManager0.getContact(contactId1);
Contact introducee2 = contactManager0.getContact(contactId2);
introductionManager0
.makeIntroduction(introducee1, introducee2, null, time);
// sync request messages
deliverMessage(sync0, contactId0, sync1, contactId1);
deliverMessage(sync0, contactId0, sync2, contactId2);
// wait for requests to arrive
eventWaiter.await(TIMEOUT, 2);
assertTrue(listener1.requestReceived);
assertTrue(listener2.requestReceived);
// sync first response
deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0");
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.response1Received);
// sync second response
deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0");
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.response2Received);
// sync both forwarded response
deliverMessage(sync0, contactId0, sync2, contactId2);
deliverMessage(sync0, contactId0, sync1, contactId1);
assertFalse(contactManager1
.contactExists(author2.getId(), author1.getId()));
assertFalse(contactManager2
.contactExists(author1.getId(), author2.getId()));
assertEquals(2,
introductionManager0.getIntroductionMessages(contactId1)
.size());
assertEquals(2,
introductionManager0.getIntroductionMessages(contactId2)
.size());
// introducee1 also sees the decline response from introducee2
assertEquals(3,
introductionManager1.getIntroductionMessages(contactId0)
.size());
assertEquals(2,
introductionManager2.getIntroductionMessages(contactId0)
.size());
} finally {
stopLifecycles();
}
}
@Test
public void testIntroductionSessionDelayedFirstDecline() throws Exception {
startLifecycles();
try {
// Add Identities
addDefaultIdentities();
// 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);
IntroduceeListener listener1 = new IntroduceeListener(1, false);
t1.getEventBus().addListener(listener1);
IntroduceeListener listener2 = new IntroduceeListener(2, false);
t2.getEventBus().addListener(listener2);
// make introduction
long time = clock.currentTimeMillis();
Contact introducee1 = contactManager0.getContact(contactId1);
Contact introducee2 = contactManager0.getContact(contactId2);
introductionManager0
.makeIntroduction(introducee1, introducee2, null, time);
// sync request messages
deliverMessage(sync0, contactId0, sync1, contactId1);
deliverMessage(sync0, contactId0, sync2, contactId2);
// wait for requests to arrive
eventWaiter.await(TIMEOUT, 2);
assertTrue(listener1.requestReceived);
assertTrue(listener2.requestReceived);
// sync first response
deliverMessage(sync1, contactId1, sync0, contactId0, "1 to 0");
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.response1Received);
// sync second response
deliverMessage(sync2, contactId2, sync0, contactId0, "2 to 0");
eventWaiter.await(TIMEOUT, 1);
assertTrue(listener0.response2Received);
// sync first forwarded response
deliverMessage(sync0, contactId0, sync2, contactId2);
// note how the second response will not be forwarded anymore
assertFalse(contactManager1
.contactExists(author2.getId(), author1.getId()));
assertFalse(contactManager2
.contactExists(author1.getId(), author2.getId()));
// since introducee2 was already in FINISHED state when
// introducee1's response arrived, she ignores and deletes it
assertDefaultUiMessages();
} finally {
stopLifecycles();
}
}
@Test
public void testIntroductionToSameContact() throws Exception {
startLifecycles();
try {
// Add Identities
addDefaultIdentities();
// 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);
IntroduceeListener listener1 = new IntroduceeListener(1, true);
t1.getEventBus().addListener(listener1);
// make introduction
long time = clock.currentTimeMillis();
Contact introducee1 = contactManager0.getContact(contactId1);
introductionManager0
.makeIntroduction(introducee1, introducee1, null, time);
// sync request messages
deliverMessage(sync0, contactId0, sync1, contactId1);
// we should not get any event, because the request will be discarded
assertFalse(listener1.requestReceived);
// make really sure we don't have that request
assertTrue(introductionManager1.getIntroductionMessages(contactId0)
.isEmpty());
} finally {
stopLifecycles();
}
}
@Test
public void testIntroductionToIdentitiesOfSameContact() throws Exception {
startLifecycles();
try {
// Add Identities
author0 = authorFactory.createLocalAuthor(INTRODUCER,
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
TestUtils.getRandomBytes(123));
identityManager0.addLocalAuthor(author0);
author1 = authorFactory.createLocalAuthor(INTRODUCEE1,
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
TestUtils.getRandomBytes(123));
identityManager1.addLocalAuthor(author1);
author2 = authorFactory.createLocalAuthor(INTRODUCEE2,
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
TestUtils.getRandomBytes(123));
identityManager1.addLocalAuthor(author2);
// Add Transport Properties
addTransportProperties();
// Add introducees' authors 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 = null;
ContactId contactId01 = contactManager1.addContact(author0,
author1.getId(), master, clock.currentTimeMillis(), false,
true
);
ContactId contactId02 = contactManager1.addContact(author0,
author2.getId(), master, clock.currentTimeMillis(), false,
true
);
// listen to events
IntroducerListener listener0 = new IntroducerListener();
t0.getEventBus().addListener(listener0);
IntroduceeListener listener1 = new IntroduceeListener(1, true);
t1.getEventBus().addListener(listener1);
// 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, contactId01, sync1, contactId1);
deliverMessage(sync0, contactId02, sync1, contactId2);
// wait for request to arrive
eventWaiter.await(TIMEOUT, 2);
assertTrue(listener1.requestReceived);
// sync responses
deliverMessage(sync1, contactId1, sync0, contactId01);
deliverMessage(sync1, contactId2, sync0, contactId02);
// wait for two responses to arrive
eventWaiter.await(TIMEOUT, 2);
assertTrue(listener0.response1Received);
assertTrue(listener0.response2Received);
// sync forwarded responses to introducees
deliverMessage(sync0, contactId01, sync1, contactId1);
deliverMessage(sync0, contactId02, sync1, contactId2);
// wait for "both" introducees to abort session
eventWaiter.await(TIMEOUT, 2);
assertTrue(listener1.aborted);
// sync abort message
deliverMessage(sync1, contactId1, sync0, contactId01);
deliverMessage(sync1, contactId2, sync0, contactId02);
// wait for introducer to abort session (gets event twice)
eventWaiter.await(TIMEOUT, 2);
assertTrue(listener0.aborted);
assertFalse(contactManager1
.contactExists(author1.getId(), author2.getId()));
assertFalse(contactManager1
.contactExists(author2.getId(), author1.getId()));
assertEquals(2, introductionManager0.getIntroductionMessages(
contactId1).size());
assertEquals(2, introductionManager0.getIntroductionMessages(
contactId2).size());
assertEquals(2, introductionManager1.getIntroductionMessages(
contactId01).size());
assertEquals(2, introductionManager1.getIntroductionMessages(
contactId02).size());
} finally {
stopLifecycles();
}
}
// TODO add a test for faking responses when #256 is implemented
@After
public void tearDown() throws InterruptedException {
TestUtils.deleteTestDirectory(testDir);
}
private void startLifecycles() throws InterruptedException {
// Start the lifecycle manager and wait for it to finish
lifecycleManager0 = t0.getLifecycleManager();
lifecycleManager1 = t1.getLifecycleManager();
lifecycleManager2 = t2.getLifecycleManager();
lifecycleManager0.startServices();
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 addTransportProperties() throws DbException {
TransportPropertyManager tpm0 = t0.getTransportPropertyManager();
TransportPropertyManager tpm1 = t1.getTransportPropertyManager();
TransportPropertyManager tpm2 = t2.getTransportPropertyManager();
TransportProperties tp = new TransportProperties(
Collections.singletonMap("key", "value"));
tpm0.mergeLocalProperties(TRANSPORT_ID, tp);
tpm1.mergeLocalProperties(TRANSPORT_ID, tp);
tpm2.mergeLocalProperties(TRANSPORT_ID, tp);
}
private void addDefaultIdentities() throws DbException {
author0 = authorFactory.createLocalAuthor(INTRODUCER,
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
TestUtils.getRandomBytes(123));
identityManager0.addLocalAuthor(author0);
author1 = authorFactory.createLocalAuthor(INTRODUCEE1,
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
TestUtils.getRandomBytes(123));
identityManager1.addLocalAuthor(author1);
author2 = authorFactory.createLocalAuthor(INTRODUCEE2,
TestUtils.getRandomBytes(MAX_PUBLIC_KEY_LENGTH),
TestUtils.getRandomBytes(123));
identityManager2.addLocalAuthor(author2);
}
private void deliverMessage(SyncSessionFactory fromSync, ContactId fromId,
SyncSessionFactory toSync, ContactId toId)
throws IOException, TimeoutException {
deliverMessage(fromSync, fromId, toSync, toId, null);
}
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 assertDefaultUiMessages() throws DbException {
assertEquals(2, introductionManager0.getIntroductionMessages(
contactId1).size());
assertEquals(2, introductionManager0.getIntroductionMessages(
contactId2).size());
assertEquals(2, introductionManager1.getIntroductionMessages(
contactId0).size());
assertEquals(2, introductionManager2.getIntroductionMessages(
contactId0).size());
}
private class IntroduceeListener implements EventListener {
public volatile boolean requestReceived = false;
public volatile boolean succeeded = false;
public volatile boolean aborted = false;
private final int introducee;
private final boolean accept;
IntroduceeListener(int introducee, boolean accept) {
this.introducee = introducee;
this.accept = accept;
}
public void eventOccurred(Event e) {
if (e instanceof MessageValidatedEvent) {
MessageValidatedEvent event = (MessageValidatedEvent) e;
if (event.getClientId()
.equals(introductionManager0.getClientId()) &&
!event.isLocal()) {
LOG.info("TEST: Introducee" + introducee +
" received message in group " +
((MessageValidatedEvent) e).getMessage()
.getGroupId().hashCode());
msgWaiter.resume();
}
} else if (e instanceof IntroductionRequestReceivedEvent) {
IntroductionRequestReceivedEvent introEvent =
((IntroductionRequestReceivedEvent) e);
requestReceived = true;
IntroductionRequest ir = introEvent.getIntroductionRequest();
ContactId contactId = introEvent.getContactId();
SessionId sessionId = ir.getSessionId();
long time = clock.currentTimeMillis();
try {
if (introducee == 1) {
if (accept) {
introductionManager1
.acceptIntroduction(contactId, sessionId,
time);
} else {
introductionManager1
.declineIntroduction(contactId, sessionId,
time);
}
} else if (introducee == 2) {
if (accept) {
introductionManager2
.acceptIntroduction(contactId, sessionId,
time);
} else {
introductionManager2
.declineIntroduction(contactId, sessionId,
time);
}
}
} catch (DbException exception) {
eventWaiter.rethrow(exception);
} catch (IOException exception) {
eventWaiter.rethrow(exception);
} finally {
eventWaiter.resume();
}
} else if (e instanceof IntroductionSucceededEvent) {
succeeded = true;
Contact contact = ((IntroductionSucceededEvent) e).getContact();
eventWaiter.assertFalse(contact.getId().equals(contactId0));
eventWaiter.assertTrue(contact.isActive());
eventWaiter.resume();
} else if (e instanceof IntroductionAbortedEvent) {
aborted = true;
eventWaiter.resume();
}
}
}
private class IntroducerListener implements EventListener {
public volatile boolean response1Received = false;
public volatile boolean response2Received = false;
public volatile boolean aborted = false;
public void eventOccurred(Event e) {
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) {
ContactId c =
((IntroductionResponseReceivedEvent) e).getContactId();
try {
if (c.equals(contactId1)) {
response1Received = true;
} else if (c.equals(contactId2)) {
response2Received = true;
}
} finally {
eventWaiter.resume();
}
} else if (e instanceof IntroductionAbortedEvent) {
aborted = true;
eventWaiter.resume();
}
}
}
private void injectEagerSingletons(
IntroductionIntegrationTestComponent component) {
component.inject(new LifecycleModule.EagerSingletons());
component.inject(new LifecycleModule.EagerSingletons());
component.inject(new IntroductionModule.EagerSingletons());
component.inject(new CryptoModule.EagerSingletons());
component.inject(new ContactModule.EagerSingletons());
component.inject(new TransportModule.EagerSingletons());
component.inject(new SyncModule.EagerSingletons());
component.inject(new PropertiesModule.EagerSingletons());
}
}

View File

@@ -0,0 +1,80 @@
package briarproject;
import org.briarproject.TestDatabaseModule;
import org.briarproject.TestPluginsModule;
import org.briarproject.TestSystemModule;
import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.event.EventBus;
import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.introduction.IntroductionManager;
import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.properties.TransportPropertyManager;
import org.briarproject.api.sync.SyncSessionFactory;
import org.briarproject.clients.ClientsModule;
import org.briarproject.contact.ContactModule;
import org.briarproject.crypto.CryptoModule;
import org.briarproject.data.DataModule;
import org.briarproject.db.DatabaseModule;
import org.briarproject.event.EventModule;
import org.briarproject.identity.IdentityModule;
import org.briarproject.introduction.IntroductionModule;
import org.briarproject.lifecycle.LifecycleModule;
import org.briarproject.properties.PropertiesModule;
import org.briarproject.sync.SyncModule;
import org.briarproject.transport.TransportModule;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = {
TestSystemModule.class,
TestDatabaseModule.class,
TestPluginsModule.class,
LifecycleModule.class,
IntroductionModule.class,
DatabaseModule.class,
CryptoModule.class,
EventModule.class,
ContactModule.class,
IdentityModule.class,
TransportModule.class,
ClientsModule.class,
SyncModule.class,
DataModule.class,
PropertiesModule.class
})
public interface IntroductionIntegrationTestComponent {
void inject(IntroductionIntegrationTest testCase);
void inject(ContactModule.EagerSingletons init);
void inject(CryptoModule.EagerSingletons init);
void inject(IntroductionModule.EagerSingletons init);
void inject(LifecycleModule.EagerSingletons init);
void inject(PropertiesModule.EagerSingletons init);
void inject(SyncModule.EagerSingletons init);
void inject(TransportModule.EagerSingletons init);
LifecycleManager getLifecycleManager();
EventBus getEventBus();
IdentityManager getIdentityManager();
ContactManager getContactManager();
IntroductionManager getIntroductionManager();
TransportPropertyManager getTransportPropertyManager();
SyncSessionFactory getSyncSessionFactory();
}

View File

@@ -0,0 +1,90 @@
package briarproject;
import org.briarproject.BriarTestCase;
import org.briarproject.TestUtils;
import org.briarproject.api.UniqueId;
import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.crypto.PrivateKey;
import org.briarproject.api.forum.ForumConstants;
import org.briarproject.api.forum.ForumPost;
import org.briarproject.api.forum.ForumPostFactory;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.messaging.MessagingConstants;
import org.briarproject.api.messaging.PrivateMessage;
import org.briarproject.api.messaging.PrivateMessageFactory;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageId;
import org.junit.Test;
import javax.inject.Inject;
import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH;
import static org.briarproject.api.sync.SyncConstants.MAX_PACKET_PAYLOAD_LENGTH;
import static org.junit.Assert.assertTrue;
public class MessageSizeIntegrationTest extends BriarTestCase {
@Inject
CryptoComponent crypto;
@Inject
AuthorFactory authorFactory;
@Inject
PrivateMessageFactory privateMessageFactory;
@Inject
ForumPostFactory forumPostFactory;
public MessageSizeIntegrationTest() throws Exception {
MessageSizeIntegrationTestComponent component =
DaggerMessageSizeIntegrationTestComponent.builder().build();
component.inject(this);
}
@Test
public void testPrivateMessageFitsIntoPacket() throws Exception {
// Create a maximum-length private message
GroupId groupId = new GroupId(TestUtils.getRandomId());
long timestamp = Long.MAX_VALUE;
MessageId parent = new MessageId(TestUtils.getRandomId());
String contentType = TestUtils.getRandomString(
MessagingConstants.MAX_CONTENT_TYPE_LENGTH);
byte[] body = new byte[MAX_PRIVATE_MESSAGE_BODY_LENGTH];
PrivateMessage message = privateMessageFactory.createPrivateMessage(
groupId, timestamp, parent, contentType, body);
// Check the size of the serialised message
int length = message.getMessage().getRaw().length;
assertTrue(length > UniqueId.LENGTH + 8 + UniqueId.LENGTH
+ MessagingConstants.MAX_CONTENT_TYPE_LENGTH
+ MAX_PRIVATE_MESSAGE_BODY_LENGTH);
assertTrue(length <= MAX_PACKET_PAYLOAD_LENGTH);
}
@Test
public void testForumPostFitsIntoPacket() throws Exception {
// Create a maximum-length author
String authorName = TestUtils.getRandomString(
MAX_AUTHOR_NAME_LENGTH);
byte[] authorPublic = new byte[MAX_PUBLIC_KEY_LENGTH];
Author author = authorFactory.createAuthor(authorName, authorPublic);
// Create a maximum-length forum post
GroupId groupId = new GroupId(TestUtils.getRandomId());
long timestamp = Long.MAX_VALUE;
MessageId parent = new MessageId(TestUtils.getRandomId());
String contentType = TestUtils.getRandomString(
ForumConstants.MAX_CONTENT_TYPE_LENGTH);
byte[] body = new byte[MAX_FORUM_POST_BODY_LENGTH];
PrivateKey privateKey = crypto.generateSignatureKeyPair().getPrivate();
ForumPost post = forumPostFactory.createPseudonymousPost(groupId,
timestamp, parent, author, contentType, body, privateKey);
// Check the size of the serialised message
int length = post.getMessage().getRaw().length;
assertTrue(length > UniqueId.LENGTH + 8 + UniqueId.LENGTH
+ MAX_AUTHOR_NAME_LENGTH + MAX_PUBLIC_KEY_LENGTH
+ ForumConstants.MAX_CONTENT_TYPE_LENGTH
+ MAX_FORUM_POST_BODY_LENGTH);
assertTrue(length <= MAX_PACKET_PAYLOAD_LENGTH);
}
}

View File

@@ -0,0 +1,37 @@
package briarproject;
import org.briarproject.TestDatabaseModule;
import org.briarproject.TestLifecycleModule;
import org.briarproject.TestSystemModule;
import org.briarproject.clients.ClientsModule;
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.messaging.MessagingModule;
import org.briarproject.sync.SyncModule;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = {
TestDatabaseModule.class,
TestLifecycleModule.class,
TestSystemModule.class,
ClientsModule.class,
CryptoModule.class,
DataModule.class,
DatabaseModule.class,
EventModule.class,
ForumModule.class,
IdentityModule.class,
MessagingModule.class,
SyncModule.class
})
public interface MessageSizeIntegrationTestComponent {
void inject(MessageSizeIntegrationTest testCase);
}

View File

@@ -0,0 +1,193 @@
package briarproject;
import org.briarproject.BriarTestCase;
import org.briarproject.TestDatabaseModule;
import org.briarproject.TestUtils;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.contact.ContactManager;
import org.briarproject.api.crypto.SecretKey;
import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventListener;
import org.briarproject.api.event.MessageAddedEvent;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.identity.IdentityManager;
import org.briarproject.api.identity.LocalAuthor;
import org.briarproject.api.lifecycle.LifecycleManager;
import org.briarproject.api.messaging.MessagingManager;
import org.briarproject.api.messaging.PrivateMessage;
import org.briarproject.api.messaging.PrivateMessageFactory;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.SyncSession;
import org.briarproject.api.sync.SyncSessionFactory;
import org.briarproject.api.transport.KeyManager;
import org.briarproject.api.transport.StreamContext;
import org.briarproject.api.transport.StreamReaderFactory;
import org.briarproject.api.transport.StreamWriterFactory;
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.InputStream;
import java.io.OutputStream;
import static org.briarproject.TestPluginsModule.MAX_LATENCY;
import static org.briarproject.TestPluginsModule.TRANSPORT_ID;
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.api.transport.TransportConstants.TAG_LENGTH;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public class SimplexMessagingIntegrationTest extends BriarTestCase {
private final File testDir = TestUtils.getTestDirectory();
private final File aliceDir = new File(testDir, "alice");
private final File bobDir = new File(testDir, "bob");
private final SecretKey master = TestUtils.getSecretKey();
private final long timestamp = System.currentTimeMillis();
private final AuthorId aliceId = new AuthorId(TestUtils.getRandomId());
private final AuthorId bobId = new AuthorId(TestUtils.getRandomId());
private SimplexMessagingIntegrationTestComponent alice, bob;
@Before
public void setUp() {
assertTrue(testDir.mkdirs());
alice = DaggerSimplexMessagingIntegrationTestComponent.builder()
.testDatabaseModule(new TestDatabaseModule(aliceDir)).build();
bob = DaggerSimplexMessagingIntegrationTestComponent.builder()
.testDatabaseModule(new TestDatabaseModule(bobDir)).build();
}
@Test
public void testWriteAndRead() throws Exception {
read(write());
}
private byte[] write() throws Exception {
// Instantiate Alice's services
LifecycleManager lifecycleManager = alice.getLifecycleManager();
IdentityManager identityManager = alice.getIdentityManager();
ContactManager contactManager = alice.getContactManager();
MessagingManager messagingManager = alice.getMessagingManager();
KeyManager keyManager = alice.getKeyManager();
PrivateMessageFactory privateMessageFactory =
alice.getPrivateMessageFactory();
StreamWriterFactory streamWriterFactory =
alice.getStreamWriterFactory();
SyncSessionFactory syncSessionFactory = alice.getSyncSessionFactory();
// Start the lifecycle manager
lifecycleManager.startServices();
lifecycleManager.waitForStartup();
// Add an identity for Alice
LocalAuthor aliceAuthor = new LocalAuthor(aliceId, "Alice",
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[123], timestamp);
identityManager.addLocalAuthor(aliceAuthor);
// Add Bob as a contact
Author bobAuthor = new Author(bobId, "Bob",
new byte[MAX_PUBLIC_KEY_LENGTH]);
ContactId contactId = contactManager.addContact(bobAuthor, aliceId,
master, timestamp, true, true);
// Send Bob a message
GroupId groupId = messagingManager.getConversationId(contactId);
byte[] body = "Hi Bob!".getBytes("UTF-8");
PrivateMessage message = privateMessageFactory.createPrivateMessage(
groupId, timestamp, null, "text/plain", body);
messagingManager.addLocalMessage(message);
// Get a stream context
StreamContext ctx = keyManager.getStreamContext(contactId,
TRANSPORT_ID);
assertNotNull(ctx);
// Create a stream writer
ByteArrayOutputStream out = new ByteArrayOutputStream();
OutputStream streamWriter = streamWriterFactory.createStreamWriter(
out, ctx);
// Create an outgoing sync session
SyncSession session = syncSessionFactory.createSimplexOutgoingSession(
contactId, MAX_LATENCY, streamWriter);
// Write whatever needs to be written
session.run();
streamWriter.close();
// Clean up
lifecycleManager.stopServices();
lifecycleManager.waitForShutdown();
// Return the contents of the stream
return out.toByteArray();
}
private void read(byte[] stream) throws Exception {
// Instantiate Bob's services
LifecycleManager lifecycleManager = bob.getLifecycleManager();
IdentityManager identityManager = bob.getIdentityManager();
ContactManager contactManager = bob.getContactManager();
KeyManager keyManager = bob.getKeyManager();
StreamReaderFactory streamReaderFactory = bob.getStreamReaderFactory();
SyncSessionFactory syncSessionFactory = bob.getSyncSessionFactory();
// Bob needs a MessagingManager even though we're not using it directly
bob.getMessagingManager();
// Start the lifecyle manager
lifecycleManager.startServices();
lifecycleManager.waitForStartup();
// Add an identity for Bob
LocalAuthor bobAuthor = new LocalAuthor(bobId, "Bob",
new byte[MAX_PUBLIC_KEY_LENGTH], new byte[123], timestamp);
identityManager.addLocalAuthor(bobAuthor);
// Add Alice as a contact
Author aliceAuthor = new Author(aliceId, "Alice",
new byte[MAX_PUBLIC_KEY_LENGTH]);
ContactId contactId = contactManager.addContact(aliceAuthor, bobId,
master, timestamp, false, true);
// Set up an event listener
MessageListener listener = new MessageListener();
bob.getEventBus().addListener(listener);
// Read and recognise the tag
ByteArrayInputStream in = new ByteArrayInputStream(stream);
byte[] tag = new byte[TAG_LENGTH];
int read = in.read(tag);
assertEquals(tag.length, read);
StreamContext ctx = keyManager.getStreamContext(TRANSPORT_ID, tag);
assertNotNull(ctx);
// Create a stream reader
InputStream streamReader = streamReaderFactory.createStreamReader(
in, ctx);
// Create an incoming sync session
SyncSession session = syncSessionFactory.createIncomingSession(
contactId, streamReader);
// No messages should have been added yet
assertFalse(listener.messageAdded);
// Read whatever needs to be read
session.run();
streamReader.close();
// The private message from Alice should have been added
assertTrue(listener.messageAdded);
// Clean up
lifecycleManager.stopServices();
lifecycleManager.waitForShutdown();
}
@After
public void tearDown() {
TestUtils.deleteTestDirectory(testDir);
}
private static class MessageListener implements EventListener {
private volatile boolean messageAdded = false;
public void eventOccurred(Event e) {
if (e instanceof MessageAddedEvent) messageAdded = true;
}
}
}

View File

@@ -0,0 +1,74 @@
package briarproject;
import org.briarproject.TestDatabaseModule;
import org.briarproject.TestPluginsModule;
import org.briarproject.TestSystemModule;
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.messaging.MessagingManager;
import org.briarproject.api.messaging.PrivateMessageFactory;
import org.briarproject.api.sync.SyncSessionFactory;
import org.briarproject.api.transport.KeyManager;
import org.briarproject.api.transport.StreamReaderFactory;
import org.briarproject.api.transport.StreamWriterFactory;
import org.briarproject.clients.ClientsModule;
import org.briarproject.contact.ContactModule;
import org.briarproject.crypto.CryptoModule;
import org.briarproject.data.DataModule;
import org.briarproject.db.DatabaseModule;
import org.briarproject.event.EventModule;
import org.briarproject.identity.IdentityModule;
import org.briarproject.lifecycle.LifecycleModule;
import org.briarproject.messaging.MessagingModule;
import org.briarproject.plugins.PluginsModule;
import org.briarproject.sync.SyncModule;
import org.briarproject.transport.TransportModule;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = {
TestDatabaseModule.class,
TestPluginsModule.class,
TestSystemModule.class,
ClientsModule.class,
ContactModule.class,
CryptoModule.class,
DataModule.class,
DatabaseModule.class,
EventModule.class,
IdentityModule.class,
LifecycleModule.class,
MessagingModule.class,
PluginsModule.class,
SyncModule.class,
TransportModule.class
})
public interface SimplexMessagingIntegrationTestComponent {
void inject(SimplexMessagingIntegrationTest testCase);
LifecycleManager getLifecycleManager();
IdentityManager getIdentityManager();
ContactManager getContactManager();
MessagingManager getMessagingManager();
KeyManager getKeyManager();
PrivateMessageFactory getPrivateMessageFactory();
EventBus getEventBus();
StreamWriterFactory getStreamWriterFactory();
StreamReaderFactory getStreamReaderFactory();
SyncSessionFactory getSyncSessionFactory();
}

View File

@@ -0,0 +1,169 @@
package briarproject;
import org.briarproject.BriarTestCase;
import org.briarproject.TestUtils;
import org.briarproject.api.TransportId;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.crypto.SecretKey;
import org.briarproject.api.sync.Ack;
import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupFactory;
import org.briarproject.api.sync.Message;
import org.briarproject.api.sync.MessageFactory;
import org.briarproject.api.sync.MessageId;
import org.briarproject.api.sync.Offer;
import org.briarproject.api.sync.PacketReader;
import org.briarproject.api.sync.PacketReaderFactory;
import org.briarproject.api.sync.PacketWriter;
import org.briarproject.api.sync.PacketWriterFactory;
import org.briarproject.api.sync.Request;
import org.briarproject.api.transport.StreamContext;
import org.briarproject.api.transport.StreamReaderFactory;
import org.briarproject.api.transport.StreamWriterFactory;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
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;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class SyncIntegrationTest extends BriarTestCase {
@Inject
GroupFactory groupFactory;
@Inject
MessageFactory messageFactory;
@Inject
StreamReaderFactory streamReaderFactory;
@Inject
StreamWriterFactory streamWriterFactory;
@Inject
PacketReaderFactory packetReaderFactory;
@Inject
PacketWriterFactory packetWriterFactory;
@Inject
CryptoComponent crypto;
private final ContactId contactId;
private final TransportId transportId;
private final SecretKey tagKey, headerKey;
private final long streamNumber;
private final Message message, message1;
private final Collection<MessageId> messageIds;
public SyncIntegrationTest() throws Exception {
SyncIntegrationTestComponent component =
DaggerSyncIntegrationTestComponent.builder().build();
component.inject(this);
contactId = new ContactId(234);
transportId = new TransportId("id");
// Create the transport keys
tagKey = TestUtils.getSecretKey();
headerKey = TestUtils.getSecretKey();
streamNumber = 123;
// Create a group
ClientId clientId = new ClientId(TestUtils.getRandomId());
byte[] descriptor = new byte[MAX_GROUP_DESCRIPTOR_LENGTH];
Group group = groupFactory.createGroup(clientId, descriptor);
// Add two messages to the group
long timestamp = System.currentTimeMillis();
byte[] body = "Hello world".getBytes("UTF-8");
message = messageFactory.createMessage(group.getId(), timestamp, body);
message1 = messageFactory.createMessage(group.getId(), timestamp, body);
messageIds = Arrays.asList(message.getId(), message1.getId());
}
@Test
public void testWriteAndRead() throws Exception {
read(write());
}
private byte[] write() throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
StreamContext ctx = new StreamContext(contactId, transportId, tagKey,
headerKey, streamNumber);
OutputStream streamWriter = streamWriterFactory.createStreamWriter(out,
ctx);
PacketWriter packetWriter = packetWriterFactory.createPacketWriter(
streamWriter);
packetWriter.writeAck(new Ack(messageIds));
packetWriter.writeMessage(message.getRaw());
packetWriter.writeMessage(message1.getRaw());
packetWriter.writeOffer(new Offer(messageIds));
packetWriter.writeRequest(new Request(messageIds));
streamWriter.flush();
return out.toByteArray();
}
private void read(byte[] connectionData) throws Exception {
// Calculate the expected tag
byte[] expectedTag = new byte[TAG_LENGTH];
crypto.encodeTag(expectedTag, tagKey, streamNumber);
// Read the tag
InputStream in = new ByteArrayInputStream(connectionData);
byte[] tag = new byte[TAG_LENGTH];
assertEquals(TAG_LENGTH, in.read(tag, 0, TAG_LENGTH));
assertArrayEquals(expectedTag, tag);
// Create the readers
StreamContext ctx = new StreamContext(contactId, transportId, tagKey,
headerKey, 0);
InputStream streamReader = streamReaderFactory.createStreamReader(in,
ctx);
PacketReader packetReader = packetReaderFactory.createPacketReader(
streamReader);
// Read the ack
assertTrue(packetReader.hasAck());
Ack a = packetReader.readAck();
assertEquals(messageIds, a.getMessageIds());
// Read the messages
assertTrue(packetReader.hasMessage());
Message m = packetReader.readMessage();
checkMessageEquality(message, m);
assertTrue(packetReader.hasMessage());
m = packetReader.readMessage();
checkMessageEquality(message1, m);
assertFalse(packetReader.hasMessage());
// Read the offer
assertTrue(packetReader.hasOffer());
Offer o = packetReader.readOffer();
assertEquals(messageIds, o.getMessageIds());
// Read the request
assertTrue(packetReader.hasRequest());
Request req = packetReader.readRequest();
assertEquals(messageIds, req.getMessageIds());
in.close();
}
private void checkMessageEquality(Message m1, Message m2) {
assertArrayEquals(m1.getId().getBytes(), m2.getId().getBytes());
assertArrayEquals(m1.getGroupId().getBytes(),
m2.getGroupId().getBytes());
assertEquals(m1.getTimestamp(), m2.getTimestamp());
assertEquals(m1.getLength(), m2.getLength());
assertArrayEquals(m1.getRaw(), m2.getRaw());
}
}

View File

@@ -0,0 +1,21 @@
package briarproject;
import org.briarproject.TestSystemModule;
import org.briarproject.crypto.CryptoModule;
import org.briarproject.sync.SyncModule;
import org.briarproject.transport.TransportModule;
import javax.inject.Singleton;
import dagger.Component;
@Singleton
@Component(modules = {
TestSystemModule.class,
CryptoModule.class,
SyncModule.class,
TransportModule.class
})
public interface SyncIntegrationTestComponent {
void inject(SyncIntegrationTest testCase);
}

View File

@@ -0,0 +1,69 @@
package briarproject.activity;
import android.support.design.widget.TextInputLayout;
import android.widget.Button;
import android.widget.EditText;
import org.briarproject.BuildConfig;
import org.briarproject.R;
import org.briarproject.android.ActivityModule;
import org.briarproject.android.SetupActivity;
import org.briarproject.android.util.StrengthMeter;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.annotation.Config;
@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 22)
public class SetupActivityTest {
private SetupActivity setupActivity;
TextInputLayout nicknameEntryWrapper;
TextInputLayout passwordEntryWrapper;
TextInputLayout passwordConfirmationWrapper;
EditText nicknameEntry;
EditText passwordEntry;
EditText passwordConfirmation;
StrengthMeter strengthMeter;
Button createAccountButton;
class TestSetupActivity extends SetupActivity {
@Override
protected ActivityModule getActivityModule() {
return super.getActivityModule();
}
}
@Before
public void setUp() {
setupActivity = Robolectric.setupActivity(SetupActivity.class);
nicknameEntryWrapper = (TextInputLayout) setupActivity
.findViewById(R.id.nickname_entry_wrapper);
passwordEntryWrapper = (TextInputLayout) setupActivity
.findViewById(R.id.password_entry_wrapper);
passwordConfirmationWrapper = (TextInputLayout) setupActivity
.findViewById(R.id.password_confirm_wrapper);
nicknameEntry =
(EditText) setupActivity.findViewById(R.id.nickname_entry);
passwordEntry =
(EditText) setupActivity.findViewById(R.id.password_entry);
passwordConfirmation =
(EditText) setupActivity.findViewById(R.id.password_confirm);
strengthMeter =
(StrengthMeter) setupActivity.findViewById(R.id.strength_meter);
createAccountButton =
(Button) setupActivity.findViewById(R.id.create_account);
}
@Test
public void test() {
}
}

View File

@@ -0,0 +1,19 @@
package briarproject.activity;
import org.briarproject.android.ActivityModule;
import org.briarproject.android.BaseActivity;
public class TestActivityModule extends ActivityModule {
public TestActivityModule(BaseActivity activity) {
super(activity);
}
/*
@Override
protected SetupController provideSetupController(
SetupControllerImp setupControllerImp) {
}
*/
}

View File

@@ -0,0 +1,17 @@
package briarproject.controller;
import org.briarproject.BriarTestCase;
import org.briarproject.android.controller.SetupController;
import org.junit.Before;
import javax.inject.Inject;
public class SetupControllerTest extends BriarTestCase {
@Inject
SetupController setupController;
@Before public void setUp() {
}
}

View File

@@ -1,6 +1,6 @@
package org.briarproject.system;
import static java.util.logging.Level.WARNING;
import org.briarproject.api.system.SeedProvider;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -13,7 +13,7 @@ import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;
import org.briarproject.api.system.SeedProvider;
import static java.util.logging.Level.WARNING;
class LinuxSeedProvider implements SeedProvider {
@@ -43,6 +43,8 @@ class LinuxSeedProvider implements SeedProvider {
} catch (IOException e) {
// On some devices /dev/urandom isn't writable - this isn't fatal
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
} catch (NullPointerException e) {
if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
}
// Read the seed from the pool
try {