implementing robolectric and mockito

parent aa3ef896
......@@ -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, ...
......
......@@ -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.**
......
......@@ -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();
}
......
......@@ -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();
......
......@@ -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;
}
......
......@@ -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
......
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();
}
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);
}
}
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);
}
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;
}
}
}
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();