mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 02:39:05 +01:00
Compare commits
6 Commits
deliver-te
...
screenshot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d5f5d4419 | ||
|
|
8393513871 | ||
|
|
38270fbee8 | ||
|
|
65c0646812 | ||
|
|
0416583e8c | ||
|
|
91f8c801b8 |
@@ -159,7 +159,8 @@ class AccountManagerImpl implements AccountManager {
|
||||
@Override
|
||||
public boolean createAccount(String name, String password) {
|
||||
synchronized (stateChangeLock) {
|
||||
// TODO don't allow creating another account if one already exists
|
||||
if (hasDatabaseKey())
|
||||
throw new AssertionError("Already have a database key");
|
||||
LocalAuthor localAuthor = identityManager.createLocalAuthor(name);
|
||||
identityManager.registerLocalAuthor(localAuthor);
|
||||
SecretKey key = crypto.generateSecretKey();
|
||||
@@ -182,6 +183,7 @@ class AccountManagerImpl implements AccountManager {
|
||||
LOG.info("Deleting account");
|
||||
IoUtils.deleteFileOrDir(databaseConfig.getDatabaseKeyDirectory());
|
||||
IoUtils.deleteFileOrDir(databaseConfig.getDatabaseDirectory());
|
||||
databaseKey = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,65 +2,6 @@ apply plugin: 'com.android.application'
|
||||
apply plugin: 'witness'
|
||||
apply from: 'witness.gradle'
|
||||
|
||||
dependencies {
|
||||
implementation project(path: ':briar-core', configuration: 'default')
|
||||
implementation project(path: ':bramble-core', configuration: 'default')
|
||||
implementation project(':bramble-android')
|
||||
|
||||
def supportVersion = '27.1.1'
|
||||
implementation "com.android.support:support-v4:$supportVersion"
|
||||
implementation("com.android.support:appcompat-v7:$supportVersion") {
|
||||
exclude module: 'support-v4'
|
||||
}
|
||||
implementation("com.android.support:preference-v14:$supportVersion") {
|
||||
exclude module: 'support-v4'
|
||||
}
|
||||
implementation("com.android.support:design:$supportVersion") {
|
||||
exclude module: 'support-v4'
|
||||
exclude module: 'recyclerview-v7'
|
||||
}
|
||||
implementation "com.android.support:cardview-v7:$supportVersion"
|
||||
implementation "com.android.support:support-annotations:$supportVersion"
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
|
||||
|
||||
implementation('ch.acra:acra:4.9.1') {
|
||||
exclude module: 'support-v4'
|
||||
exclude module: 'support-annotations'
|
||||
}
|
||||
implementation 'info.guardianproject.panic:panic:0.5'
|
||||
implementation 'info.guardianproject.trustedintents:trustedintents:0.2'
|
||||
implementation 'de.hdodenhof:circleimageview:2.2.0'
|
||||
implementation 'com.google.zxing:core:3.3.0'
|
||||
implementation 'uk.co.samuelwall:material-tap-target-prompt:2.8.0'
|
||||
implementation 'com.vanniktech:emoji-google:0.5.1'
|
||||
|
||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
|
||||
|
||||
compileOnly 'javax.annotation:jsr250-api:1.0'
|
||||
|
||||
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
|
||||
testImplementation project(path: ':bramble-core', configuration: 'testOutput')
|
||||
testImplementation 'org.robolectric:robolectric:3.8'
|
||||
testImplementation 'org.robolectric:shadows-support-v4:3.3.2'
|
||||
testImplementation 'org.mockito:mockito-core:2.13.0'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
testImplementation "org.jmock:jmock:2.8.2"
|
||||
testImplementation "org.jmock:jmock-junit4:2.8.2"
|
||||
testImplementation "org.jmock:jmock-legacy:2.8.2"
|
||||
testImplementation "org.hamcrest:hamcrest-library:1.3"
|
||||
testImplementation "org.hamcrest:hamcrest-core:1.3"
|
||||
|
||||
def espressoVersion = '3.0.2'
|
||||
androidTestImplementation "com.android.support.test.espresso:espresso-core:$espressoVersion"
|
||||
androidTestImplementation "com.android.support.test.espresso:espresso-contrib:$espressoVersion"
|
||||
androidTestImplementation "com.android.support.test.espresso:espresso-intents:$espressoVersion"
|
||||
androidTestImplementation "tools.fastlane:screengrab:1.1.0"
|
||||
androidTestImplementation "com.android.support.test.uiautomator:uiautomator-v18:2.1.3"
|
||||
androidTestAnnotationProcessor "com.google.dagger:dagger-compiler:2.0.2"
|
||||
androidTestCompileOnly 'javax.annotation:jsr250-api:1.0'
|
||||
androidTestImplementation 'junit:junit:4.12'
|
||||
}
|
||||
|
||||
def getStdout = { command, defaultValue ->
|
||||
def stdout = new ByteArrayOutputStream()
|
||||
try {
|
||||
@@ -89,7 +30,7 @@ android {
|
||||
def now = (long) (System.currentTimeMillis() / 1000)
|
||||
buildConfigField "Long", "BuildTimestamp",
|
||||
"${getStdout(['git', 'log', '-n', '1', '--format=%ct'], now)}000L"
|
||||
testInstrumentationRunner 'org.briarproject.briar.android.test.BriarTestRunner'
|
||||
testInstrumentationRunner 'org.briarproject.briar.android.BriarTestRunner'
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@@ -144,6 +85,68 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(path: ':briar-core', configuration: 'default')
|
||||
implementation project(path: ':bramble-core', configuration: 'default')
|
||||
implementation project(':bramble-android')
|
||||
|
||||
def supportVersion = '27.1.1'
|
||||
implementation "com.android.support:support-v4:$supportVersion"
|
||||
implementation("com.android.support:appcompat-v7:$supportVersion") {
|
||||
exclude module: 'support-v4'
|
||||
}
|
||||
implementation("com.android.support:preference-v14:$supportVersion") {
|
||||
exclude module: 'support-v4'
|
||||
}
|
||||
implementation("com.android.support:design:$supportVersion") {
|
||||
exclude module: 'support-v4'
|
||||
exclude module: 'recyclerview-v7'
|
||||
}
|
||||
implementation "com.android.support:cardview-v7:$supportVersion"
|
||||
implementation "com.android.support:support-annotations:$supportVersion"
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
|
||||
|
||||
implementation('ch.acra:acra:4.9.1') {
|
||||
exclude module: 'support-v4'
|
||||
exclude module: 'support-annotations'
|
||||
}
|
||||
implementation 'info.guardianproject.panic:panic:0.5'
|
||||
implementation 'info.guardianproject.trustedintents:trustedintents:0.2'
|
||||
implementation 'de.hdodenhof:circleimageview:2.2.0'
|
||||
implementation 'com.google.zxing:core:3.3.0'
|
||||
implementation 'uk.co.samuelwall:material-tap-target-prompt:2.8.0'
|
||||
implementation 'com.vanniktech:emoji-google:0.5.1'
|
||||
|
||||
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
|
||||
|
||||
compileOnly 'javax.annotation:jsr250-api:1.0'
|
||||
|
||||
testImplementation project(path: ':bramble-api', configuration: 'testOutput')
|
||||
testImplementation project(path: ':bramble-core', configuration: 'testOutput')
|
||||
testImplementation 'org.robolectric:robolectric:3.8'
|
||||
testImplementation 'org.robolectric:shadows-support-v4:3.3.2'
|
||||
testImplementation 'org.mockito:mockito-core:2.13.0'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
testImplementation "org.jmock:jmock:2.8.2"
|
||||
testImplementation "org.jmock:jmock-junit4:2.8.2"
|
||||
testImplementation "org.jmock:jmock-legacy:2.8.2"
|
||||
testImplementation "org.hamcrest:hamcrest-library:1.3"
|
||||
testImplementation "org.hamcrest:hamcrest-core:1.3"
|
||||
|
||||
def espressoVersion = '3.0.2'
|
||||
androidTestImplementation "com.android.support.test.espresso:espresso-core:$espressoVersion"
|
||||
androidTestImplementation "com.android.support.test.espresso:espresso-contrib:$espressoVersion"
|
||||
androidTestImplementation "com.android.support.test.espresso:espresso-intents:$espressoVersion"
|
||||
androidTestAnnotationProcessor "com.google.dagger:dagger-compiler:2.0.2"
|
||||
androidTestCompileOnly 'javax.annotation:jsr250-api:1.0'
|
||||
androidTestImplementation 'junit:junit:4.12'
|
||||
|
||||
androidTestScreenshotImplementation project(path: ':bramble-api', configuration: 'testOutput')
|
||||
androidTestScreenshotImplementation project(path: ':bramble-core', configuration: 'testOutput')
|
||||
androidTestScreenshotImplementation "tools.fastlane:screengrab:1.2.0"
|
||||
androidTestScreenshotImplementation "com.android.support.test.uiautomator:uiautomator-v18:2.1.3"
|
||||
}
|
||||
|
||||
task verifyTranslations {
|
||||
doLast {
|
||||
def file = project.file("src/main/res/values/arrays.xml")
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
app_package_name "org.briarproject.briar.android.screenshot.debug"
|
||||
locales ['en-US']
|
||||
use_tests_in_classes([
|
||||
'org.briarproject.briar.android.login.SetupActivityScreenshotTest',
|
||||
'org.briarproject.briar.android.settings.SettingsActivityScreenshotTest',
|
||||
])
|
||||
app_apk_path "build/outputs/apk/screenshot/debug/briar-android-screenshot-debug.apk"
|
||||
tests_apk_path "build/outputs/apk/androidTest/screenshot/debug/briar-android-screenshot-debug-androidTest.apk"
|
||||
test_instrumentation_runner "org.briarproject.briar.android.test.BriarTestRunner"
|
||||
test_instrumentation_runner "org.briarproject.briar.android.BriarTestRunner"
|
||||
reinstall_app = true
|
||||
exit_on_test_failure = true
|
||||
@@ -4,4 +4,8 @@ adb shell am broadcast -a com.android.systemui.demo -e command enter
|
||||
adb shell am broadcast -a com.android.systemui.demo -e command notifications -e visible false
|
||||
adb shell am broadcast -a com.android.systemui.demo -e command battery -e level 100
|
||||
adb shell am broadcast -a com.android.systemui.demo -e command network -e wifi show
|
||||
adb shell am broadcast -a com.android.systemui.demo -e command clock -e hhmm 1337
|
||||
adb shell am broadcast -a com.android.systemui.demo -e command clock -e hhmm 1337
|
||||
|
||||
# workaround for Android Pie hidden API Espresso bug
|
||||
adb shell settings put global hidden_api_policy_pre_p_apps 1
|
||||
adb shell settings put global hidden_api_policy_p_apps 1
|
||||
|
||||
@@ -28,3 +28,5 @@
|
||||
|
||||
# Emoji
|
||||
-keep class com.vanniktech.emoji.**
|
||||
|
||||
-keepclasseswithmembers public class android.support.v7.widget.RecyclerView { *; }
|
||||
|
||||
@@ -12,4 +12,5 @@
|
||||
-keep class junit.** { *; }
|
||||
-dontwarn junit.**
|
||||
|
||||
-dontwarn org.briarproject.briar.android.BriarTestComponentApplication
|
||||
-dontwarn org.briarproject.briar.android.**
|
||||
-dontwarn org.briarproject.bramble.**
|
||||
|
||||
@@ -8,7 +8,7 @@ public class BriarTestComponentApplication extends BriarApplicationImpl {
|
||||
@Override
|
||||
protected AndroidComponent createApplicationComponent() {
|
||||
AndroidComponent component = DaggerBriarUiTestComponent.builder()
|
||||
.appModule(new AppModule(this)).build();
|
||||
.testAppModule(new TestAppModule(this)).build();
|
||||
// We need to load the eager singletons directly after making the
|
||||
// dependency graphs
|
||||
BrambleCoreModule.initEagerSingletons(component);
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package org.briarproject.briar.android.test;
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.support.test.runner.AndroidJUnitRunner;
|
||||
|
||||
import org.briarproject.briar.android.BriarTestComponentApplication;
|
||||
|
||||
public class BriarTestRunner extends AndroidJUnitRunner {
|
||||
|
||||
@Override
|
||||
@@ -13,8 +11,8 @@ public class BriarTestRunner extends AndroidJUnitRunner {
|
||||
Context context)
|
||||
throws InstantiationException, IllegalAccessException,
|
||||
ClassNotFoundException {
|
||||
return super.newApplication(cl, BriarTestComponentApplication.class.getName(),
|
||||
context);
|
||||
return super.newApplication(cl,
|
||||
BriarTestComponentApplication.class.getName(), context);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.support.test.espresso.intent.rule.IntentsTestRule;
|
||||
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.briar.R;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static android.support.test.InstrumentationRegistry.getTargetContext;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public abstract class UiTest {
|
||||
|
||||
protected final String USERNAME =
|
||||
getTargetContext().getString(R.string.screenshot_alice);
|
||||
protected static final String PASSWORD = "123456";
|
||||
|
||||
protected final BriarUiTestComponent alice;
|
||||
|
||||
@Inject
|
||||
protected AccountManager accountManager;
|
||||
@Inject
|
||||
protected LifecycleManager lifecycleManager;
|
||||
|
||||
public UiTest() {
|
||||
BriarTestComponentApplication app =
|
||||
(BriarTestComponentApplication) getTargetContext()
|
||||
.getApplicationContext();
|
||||
alice = (BriarUiTestComponent) app.getApplicationComponent();
|
||||
inject(alice);
|
||||
}
|
||||
|
||||
protected abstract void inject(BriarUiTestComponent component);
|
||||
|
||||
@NotNullByDefault
|
||||
protected class CleanAccountTestRule<A extends Activity>
|
||||
extends IntentsTestRule<A> {
|
||||
|
||||
@Nullable
|
||||
private final Runnable runnable;
|
||||
|
||||
public CleanAccountTestRule(Class<A> activityClass) {
|
||||
super(activityClass);
|
||||
this.runnable = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this if you need to run code before launching the activity.
|
||||
* Note: You need to use {@link #launchActivity(Intent)} yourself
|
||||
* to start the activity.
|
||||
*/
|
||||
public CleanAccountTestRule(Class<A> activityClass, Runnable runnable) {
|
||||
super(activityClass, false, false);
|
||||
this.runnable = runnable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeActivityLaunched() {
|
||||
super.beforeActivityLaunched();
|
||||
accountManager.deleteAccount();
|
||||
accountManager.createAccount(USERNAME, PASSWORD);
|
||||
if (runnable != null) {
|
||||
Intent serviceIntent =
|
||||
new Intent(getTargetContext(), BriarService.class);
|
||||
getTargetContext().startService(serviceIntent);
|
||||
try {
|
||||
lifecycleManager.waitForStartup();
|
||||
} catch (InterruptedException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
runnable.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.briar.android.test;
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.support.test.espresso.PerformException;
|
||||
@@ -1,106 +0,0 @@
|
||||
package org.briarproject.briar.android.login;
|
||||
|
||||
import android.support.test.espresso.intent.rule.IntentsTestRule;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.support.test.uiautomator.UiDevice;
|
||||
import android.support.test.uiautomator.UiObject;
|
||||
import android.support.test.uiautomator.UiSelector;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.BriarUiTestComponent;
|
||||
import org.briarproject.briar.android.test.ScreenshotTest;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static android.support.test.InstrumentationRegistry.getInstrumentation;
|
||||
import static android.support.test.InstrumentationRegistry.getTargetContext;
|
||||
import static android.support.test.espresso.Espresso.onView;
|
||||
import static android.support.test.espresso.action.ViewActions.click;
|
||||
import static android.support.test.espresso.action.ViewActions.typeText;
|
||||
import static android.support.test.espresso.assertion.ViewAssertions.matches;
|
||||
import static android.support.test.espresso.intent.Intents.intended;
|
||||
import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static android.support.test.runner.lifecycle.Stage.PAUSED;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static org.briarproject.briar.android.test.ViewActions.waitForActivity;
|
||||
import static org.briarproject.briar.android.test.ViewActions.waitUntilMatches;
|
||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class SetupActivityScreenshotTest extends ScreenshotTest {
|
||||
|
||||
@Rule
|
||||
public IntentsTestRule<SetupActivity> testRule =
|
||||
new IntentsTestRule<SetupActivity>(SetupActivity.class) {
|
||||
@Override
|
||||
protected void beforeActivityLaunched() {
|
||||
super.beforeActivityLaunched();
|
||||
accountManager.deleteAccount();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void inject(BriarUiTestComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createAccount() throws Exception {
|
||||
// Enter username
|
||||
onView(withText(R.string.setup_title))
|
||||
.check(matches(isDisplayed()));
|
||||
onView(withId(R.id.nickname_entry))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(typeText(USERNAME));
|
||||
onView(withId(R.id.nickname_entry))
|
||||
.perform(waitUntilMatches(withText(USERNAME)));
|
||||
|
||||
screenshot("manual_create_account");
|
||||
|
||||
onView(withId(R.id.next))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(click());
|
||||
|
||||
// Enter password
|
||||
onView(withId(R.id.password_entry))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(typeText(PASSWORD));
|
||||
onView(withId(R.id.password_confirm))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(typeText(PASSWORD));
|
||||
onView(withId(R.id.next))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(click());
|
||||
|
||||
// White-list Doze if needed
|
||||
if (needsDozeWhitelisting(getTargetContext())) {
|
||||
onView(withText(R.string.setup_doze_button))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(click());
|
||||
UiDevice device = UiDevice.getInstance(getInstrumentation());
|
||||
UiObject allowButton = device.findObject(
|
||||
new UiSelector().className("android.widget.Button")
|
||||
.index(1));
|
||||
allowButton.click();
|
||||
onView(withId(R.id.next))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(click());
|
||||
}
|
||||
|
||||
// wait for OpenDatabaseActivity to show up
|
||||
onView(withId(R.id.progress))
|
||||
.check(matches(isDisplayed()));
|
||||
onView(isRoot())
|
||||
.perform(waitForActivity(testRule.getActivity(), PAUSED));
|
||||
intended(hasComponent(OpenDatabaseActivity.class.getName()));
|
||||
|
||||
assertTrue(accountManager.hasDatabaseKey());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
package org.briarproject.briar.android.test;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.support.test.espresso.intent.rule.IntentsTestRule;
|
||||
import android.util.Log;
|
||||
|
||||
import org.briarproject.bramble.api.account.AccountManager;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.briar.android.BriarTestComponentApplication;
|
||||
import org.briarproject.briar.android.BriarUiTestComponent;
|
||||
import org.junit.ClassRule;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import tools.fastlane.screengrab.Screengrab;
|
||||
import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy;
|
||||
import tools.fastlane.screengrab.locale.LocaleTestRule;
|
||||
|
||||
import static android.support.test.InstrumentationRegistry.getTargetContext;
|
||||
import static tools.fastlane.screengrab.Screengrab.setDefaultScreenshotStrategy;
|
||||
|
||||
public abstract class ScreenshotTest {
|
||||
|
||||
@ClassRule
|
||||
public static final LocaleTestRule localeTestRule = new LocaleTestRule();
|
||||
|
||||
protected static final String USERNAME = "Alice";
|
||||
protected static final String PASSWORD = "123456";
|
||||
|
||||
@Inject
|
||||
protected AccountManager accountManager;
|
||||
@Inject
|
||||
protected LifecycleManager lifecycleManager;
|
||||
|
||||
public ScreenshotTest() {
|
||||
super();
|
||||
setDefaultScreenshotStrategy(new UiAutomatorScreenshotStrategy());
|
||||
BriarTestComponentApplication app =
|
||||
(BriarTestComponentApplication) getTargetContext()
|
||||
.getApplicationContext();
|
||||
inject((BriarUiTestComponent) app.getApplicationComponent());
|
||||
}
|
||||
|
||||
protected abstract void inject(BriarUiTestComponent component);
|
||||
|
||||
protected void screenshot(String name) {
|
||||
try {
|
||||
Screengrab.screenshot(name);
|
||||
} catch (RuntimeException e) {
|
||||
if (!e.getMessage().equals("Unable to capture screenshot."))
|
||||
throw e;
|
||||
// The tests should still pass when run from AndroidStudio
|
||||
// without manually granting permissions like fastlane does.
|
||||
Log.w("Screengrab", "Permission to write screenshot is missing.");
|
||||
}
|
||||
}
|
||||
|
||||
protected class CleanAccountTestRule<A extends Activity>
|
||||
extends IntentsTestRule<A> {
|
||||
|
||||
public CleanAccountTestRule(Class<A> activityClass) {
|
||||
super(activityClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeActivityLaunched() {
|
||||
super.beforeActivityLaunched();
|
||||
accountManager.deleteAccount();
|
||||
accountManager.createAccount(USERNAME, PASSWORD);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,9 +4,7 @@ import org.briarproject.bramble.BrambleAndroidModule;
|
||||
import org.briarproject.bramble.BrambleCoreModule;
|
||||
import org.briarproject.bramble.account.BriarAccountModule;
|
||||
import org.briarproject.briar.BriarCoreModule;
|
||||
import org.briarproject.briar.android.login.SetupActivityScreenshotTest;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerActivityTest;
|
||||
import org.briarproject.briar.android.settings.SettingsActivityScreenshotTest;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
@@ -22,8 +20,6 @@ import dagger.Component;
|
||||
})
|
||||
public interface BriarUiTestComponent extends AndroidComponent {
|
||||
|
||||
void inject(SetupActivityScreenshotTest test);
|
||||
void inject(NavDrawerActivityTest test);
|
||||
void inject(SettingsActivityScreenshotTest test);
|
||||
|
||||
}
|
||||
@@ -6,8 +6,8 @@ import android.view.Gravity;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.BriarUiTestComponent;
|
||||
import org.briarproject.briar.android.UiTest;
|
||||
import org.briarproject.briar.android.settings.SettingsActivity;
|
||||
import org.briarproject.briar.android.test.ScreenshotTest;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -23,7 +23,7 @@ import static android.support.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withText;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class NavDrawerActivityTest extends ScreenshotTest {
|
||||
public class NavDrawerActivityTest extends UiTest {
|
||||
|
||||
@Rule
|
||||
public CleanAccountTestRule<NavDrawerActivity> testRule =
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import org.briarproject.bramble.BrambleAndroidModule;
|
||||
import org.briarproject.bramble.BrambleCoreModule;
|
||||
import org.briarproject.bramble.account.BriarAccountModule;
|
||||
import org.briarproject.briar.BriarCoreModule;
|
||||
import org.briarproject.briar.android.contact.ConversationActivityScreenshotTest;
|
||||
import org.briarproject.briar.android.settings.SettingsActivityScreenshotTest;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Component;
|
||||
|
||||
@Singleton
|
||||
@Component(modules = {
|
||||
TestAppModule.class,
|
||||
BriarCoreModule.class,
|
||||
BrambleAndroidModule.class,
|
||||
BriarAccountModule.class,
|
||||
BrambleCoreModule.class
|
||||
})
|
||||
public interface BriarUiTestComponent extends AndroidComponent, FakeDataTestComponent {
|
||||
|
||||
void inject(SetupDataTest test);
|
||||
|
||||
void inject(ConversationActivityScreenshotTest test);
|
||||
void inject(SettingsActivityScreenshotTest test);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import org.briarproject.bramble.api.contact.ContactManager;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.sync.SyncSessionFactory;
|
||||
import org.briarproject.bramble.api.transport.KeyManager;
|
||||
import org.briarproject.bramble.api.transport.StreamReaderFactory;
|
||||
import org.briarproject.bramble.api.transport.StreamWriterFactory;
|
||||
import org.briarproject.bramble.client.ClientModule;
|
||||
import org.briarproject.bramble.contact.ContactModule;
|
||||
import org.briarproject.bramble.crypto.CryptoModule;
|
||||
import org.briarproject.bramble.data.DataModule;
|
||||
import org.briarproject.bramble.db.DatabaseModule;
|
||||
import org.briarproject.bramble.event.EventModule;
|
||||
import org.briarproject.bramble.identity.IdentityModule;
|
||||
import org.briarproject.bramble.lifecycle.LifecycleModule;
|
||||
import org.briarproject.bramble.record.RecordModule;
|
||||
import org.briarproject.bramble.sync.SyncModule;
|
||||
import org.briarproject.bramble.system.SystemModule;
|
||||
import org.briarproject.bramble.test.TestCryptoExecutorModule;
|
||||
import org.briarproject.bramble.test.TestDatabaseModule;
|
||||
import org.briarproject.bramble.test.TestSecureRandomModule;
|
||||
import org.briarproject.bramble.transport.TransportModule;
|
||||
import org.briarproject.bramble.versioning.VersioningModule;
|
||||
import org.briarproject.briar.api.messaging.MessagingManager;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
|
||||
import org.briarproject.briar.client.BriarClientModule;
|
||||
import org.briarproject.briar.messaging.MessagingModule;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Component;
|
||||
|
||||
@Singleton
|
||||
@Component(modules = {
|
||||
TestCryptoExecutorModule.class,
|
||||
TestDatabaseModule.class,
|
||||
TestPluginConfigModule.class,
|
||||
TestSecureRandomModule.class,
|
||||
BriarClientModule.class,
|
||||
ClientModule.class,
|
||||
ContactModule.class,
|
||||
CryptoModule.class,
|
||||
DataModule.class,
|
||||
DatabaseModule.class,
|
||||
EventModule.class,
|
||||
IdentityModule.class,
|
||||
LifecycleModule.class,
|
||||
MessagingModule.class,
|
||||
RecordModule.class,
|
||||
SyncModule.class,
|
||||
SystemModule.class,
|
||||
TransportModule.class,
|
||||
VersioningModule.class
|
||||
})
|
||||
interface FakeDataTestComponent {
|
||||
|
||||
void inject(ContactModule.EagerSingletons init);
|
||||
|
||||
void inject(IdentityModule.EagerSingletons init);
|
||||
|
||||
void inject(LifecycleModule.EagerSingletons init);
|
||||
|
||||
void inject(MessagingModule.EagerSingletons init);
|
||||
|
||||
void inject(SyncModule.EagerSingletons init);
|
||||
|
||||
void inject(SystemModule.EagerSingletons init);
|
||||
|
||||
void inject(TransportModule.EagerSingletons init);
|
||||
|
||||
void inject(VersioningModule.EagerSingletons init);
|
||||
|
||||
LifecycleManager getLifecycleManager();
|
||||
|
||||
IdentityManager getIdentityManager();
|
||||
|
||||
ContactManager getContactManager();
|
||||
|
||||
MessagingManager getMessagingManager();
|
||||
|
||||
KeyManager getKeyManager();
|
||||
|
||||
PrivateMessageFactory getPrivateMessageFactory();
|
||||
|
||||
EventBus getEventBus();
|
||||
|
||||
StreamWriterFactory getStreamWriterFactory();
|
||||
|
||||
StreamReaderFactory getStreamReaderFactory();
|
||||
|
||||
SyncSessionFactory getSyncSessionFactory();
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.util.Log;
|
||||
|
||||
import org.briarproject.bramble.api.plugin.ConnectionRegistry;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.briar.api.test.TestDataCreator;
|
||||
import org.junit.ClassRule;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import tools.fastlane.screengrab.FalconScreenshotStrategy;
|
||||
import tools.fastlane.screengrab.Screengrab;
|
||||
import tools.fastlane.screengrab.locale.LocaleTestRule;
|
||||
|
||||
public abstract class ScreenshotTest extends UiTest {
|
||||
|
||||
@ClassRule
|
||||
public static final LocaleTestRule localeTestRule = new LocaleTestRule();
|
||||
|
||||
@Inject
|
||||
protected TestDataCreator testDataCreator;
|
||||
@Inject
|
||||
protected ConnectionRegistry connectionRegistry;
|
||||
@Inject
|
||||
protected Clock clock;
|
||||
|
||||
protected void screenshot(String name, Activity activity) {
|
||||
try {
|
||||
Screengrab.screenshot(name, new FalconScreenshotStrategy(activity));
|
||||
} catch (RuntimeException e) {
|
||||
if (!e.getMessage().equals("Unable to capture screenshot."))
|
||||
throw e;
|
||||
// The tests should still pass when run from AndroidStudio
|
||||
// without manually granting permissions like fastlane does.
|
||||
Log.w("Screengrab", "Permission to write screenshot is missing.");
|
||||
}
|
||||
}
|
||||
|
||||
protected long getMinutesAgo(int minutes) {
|
||||
return clock.currentTimeMillis() - minutes * 60 * 1000;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import android.support.test.espresso.intent.rule.IntentsTestRule;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.support.test.uiautomator.UiDevice;
|
||||
import android.support.test.uiautomator.UiObject;
|
||||
import android.support.test.uiautomator.UiSelector;
|
||||
import android.util.Log;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.contact.ContactId;
|
||||
import org.briarproject.bramble.api.crypto.SecretKey;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.sync.GroupId;
|
||||
import org.briarproject.bramble.api.sync.SyncSession;
|
||||
import org.briarproject.bramble.api.sync.SyncSessionFactory;
|
||||
import org.briarproject.bramble.api.transport.KeyManager;
|
||||
import org.briarproject.bramble.api.transport.StreamContext;
|
||||
import org.briarproject.bramble.api.transport.StreamReaderFactory;
|
||||
import org.briarproject.bramble.api.transport.StreamWriter;
|
||||
import org.briarproject.bramble.api.transport.StreamWriterFactory;
|
||||
import org.briarproject.bramble.contact.ContactModule;
|
||||
import org.briarproject.bramble.identity.IdentityModule;
|
||||
import org.briarproject.bramble.lifecycle.LifecycleModule;
|
||||
import org.briarproject.bramble.sync.SyncModule;
|
||||
import org.briarproject.bramble.system.SystemModule;
|
||||
import org.briarproject.bramble.test.TestDatabaseModule;
|
||||
import org.briarproject.bramble.test.TestUtils;
|
||||
import org.briarproject.bramble.transport.TransportModule;
|
||||
import org.briarproject.bramble.versioning.VersioningModule;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.login.OpenDatabaseActivity;
|
||||
import org.briarproject.briar.android.login.SetupActivity;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
||||
import org.briarproject.briar.api.messaging.MessagingManager;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessage;
|
||||
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
|
||||
import org.briarproject.briar.messaging.MessagingModule;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
import static android.support.test.InstrumentationRegistry.getInstrumentation;
|
||||
import static android.support.test.InstrumentationRegistry.getTargetContext;
|
||||
import static android.support.test.espresso.Espresso.onView;
|
||||
import static android.support.test.espresso.action.ViewActions.click;
|
||||
import static android.support.test.espresso.action.ViewActions.typeText;
|
||||
import static android.support.test.espresso.assertion.ViewAssertions.matches;
|
||||
import static android.support.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition;
|
||||
import static android.support.test.espresso.intent.Intents.intended;
|
||||
import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static android.support.test.runner.lifecycle.Stage.PAUSED;
|
||||
import static org.briarproject.bramble.api.plugin.LanTcpConstants.ID;
|
||||
import static org.briarproject.bramble.api.transport.TransportConstants.TAG_LENGTH;
|
||||
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
|
||||
import static org.briarproject.briar.android.TestPluginConfigModule.MAX_LATENCY;
|
||||
import static org.briarproject.briar.android.TestPluginConfigModule.TRANSPORT_ID;
|
||||
import static org.briarproject.briar.android.ViewActions.waitForActivity;
|
||||
import static org.briarproject.briar.android.ViewActions.waitUntilMatches;
|
||||
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class SetupDataTest extends ScreenshotTest {
|
||||
|
||||
@Rule
|
||||
public IntentsTestRule<SetupActivity> testRule =
|
||||
new IntentsTestRule<SetupActivity>(SetupActivity.class) {
|
||||
@Override
|
||||
protected void beforeActivityLaunched() {
|
||||
super.beforeActivityLaunched();
|
||||
accountManager.deleteAccount();
|
||||
}
|
||||
};
|
||||
|
||||
private FakeDataTestComponent bob;
|
||||
private final File testDir =
|
||||
getTargetContext().getDir("test", MODE_PRIVATE);
|
||||
private final File bobDir = new File(testDir, "bob");
|
||||
private final SecretKey master = getSecretKey();
|
||||
|
||||
@Override
|
||||
protected void inject(BriarUiTestComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
Log.e("TEST", testDir.getAbsolutePath());
|
||||
Log.e("TEST", "exists: " + testDir.exists());
|
||||
assertTrue(testDir.mkdirs());
|
||||
bob = DaggerFakeDataTestComponent.builder()
|
||||
.testDatabaseModule(new TestDatabaseModule(bobDir)).build();
|
||||
injectEagerSingletons(bob);
|
||||
Log.e("TEST", "built bob");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
// Stop the lifecycle manager
|
||||
LifecycleManager lifecycleManager = bob.getLifecycleManager();
|
||||
lifecycleManager.stopServices();
|
||||
lifecycleManager.waitForShutdown();
|
||||
|
||||
TestUtils.deleteTestDirectory(testDir);
|
||||
}
|
||||
|
||||
private static void injectEagerSingletons(FakeDataTestComponent component) {
|
||||
component.inject(new ContactModule.EagerSingletons());
|
||||
component.inject(new IdentityModule.EagerSingletons());
|
||||
component.inject(new LifecycleModule.EagerSingletons());
|
||||
component.inject(new MessagingModule.EagerSingletons());
|
||||
component.inject(new SyncModule.EagerSingletons());
|
||||
component.inject(new SystemModule.EagerSingletons());
|
||||
component.inject(new TransportModule.EagerSingletons());
|
||||
component.inject(new VersioningModule.EagerSingletons());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void createAccount() throws Exception {
|
||||
// Enter username
|
||||
onView(withText(R.string.setup_title))
|
||||
.check(matches(isDisplayed()));
|
||||
onView(withId(R.id.nickname_entry))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(typeText(USERNAME));
|
||||
onView(withId(R.id.nickname_entry))
|
||||
.perform(waitUntilMatches(withText(USERNAME)));
|
||||
|
||||
screenshot("manual_create_account", testRule.getActivity());
|
||||
|
||||
onView(withId(R.id.next))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(click());
|
||||
|
||||
// Enter password
|
||||
onView(withId(R.id.password_entry))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(typeText(PASSWORD));
|
||||
onView(withId(R.id.password_confirm))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(typeText(PASSWORD));
|
||||
onView(withId(R.id.next))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(click());
|
||||
|
||||
// White-list Doze if needed
|
||||
if (needsDozeWhitelisting(getTargetContext())) {
|
||||
onView(withText(R.string.setup_doze_button))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(click());
|
||||
UiDevice device = UiDevice.getInstance(getInstrumentation());
|
||||
UiObject allowButton = device.findObject(
|
||||
new UiSelector().className("android.widget.Button")
|
||||
.index(1));
|
||||
allowButton.click();
|
||||
onView(withId(R.id.next))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(click());
|
||||
}
|
||||
|
||||
// wait for OpenDatabaseActivity to show up
|
||||
onView(isRoot())
|
||||
.perform(waitForActivity(testRule.getActivity(), PAUSED));
|
||||
intended(hasComponent(OpenDatabaseActivity.class.getName()));
|
||||
|
||||
assertTrue(accountManager.hasDatabaseKey());
|
||||
|
||||
// WIP below
|
||||
|
||||
// wait for OpenDatabaseActivity to go away
|
||||
onView(isRoot())
|
||||
.perform(waitUntilMatches(
|
||||
allOf(withId(R.id.progressBar), not(isDisplayed()))));
|
||||
lifecycleManager.waitForStartup();
|
||||
intended(hasComponent(NavDrawerActivity.class.getName()));
|
||||
|
||||
// close expiry warning
|
||||
onView(withId(R.id.expiryWarningClose))
|
||||
.check(matches(isDisplayed()));
|
||||
onView(withId(R.id.expiryWarningClose))
|
||||
.perform(click());
|
||||
|
||||
LocalAuthor aliceAuthor = alice.identityManager().getLocalAuthor();
|
||||
|
||||
LocalAuthor bobAuthor = bob.getIdentityManager().createLocalAuthor(
|
||||
getTargetContext().getString(R.string.screenshot_bob));
|
||||
bob.getIdentityManager().registerLocalAuthor(bobAuthor);
|
||||
// Start the lifecycle manager
|
||||
bob.getLifecycleManager().startServices(getSecretKey());
|
||||
bob.getLifecycleManager().waitForStartup();
|
||||
long timestamp = clock.currentTimeMillis();
|
||||
// Bob adds Alice as a contact
|
||||
ContactId aliceContactId = bob.getContactManager()
|
||||
.addContact(aliceAuthor, bobAuthor.getId(), master,
|
||||
timestamp, true, true, true);
|
||||
// Alice adds Bob as a contact
|
||||
ContactId bobContactId = alice.contactManager()
|
||||
.addContact(bobAuthor, aliceAuthor.getId(), master,
|
||||
timestamp, false, true, true);
|
||||
|
||||
// TODO figure out how many messages
|
||||
read(alice, bobContactId, write(bob, aliceContactId));
|
||||
read(bob, aliceContactId, write(alice, bobContactId));
|
||||
read(alice, bobContactId, write(bob, aliceContactId));
|
||||
read(bob, aliceContactId, write(alice, bobContactId));
|
||||
read(alice, bobContactId, write(bob, aliceContactId));
|
||||
read(bob, aliceContactId, write(alice, bobContactId));
|
||||
read(alice, bobContactId, write(bob, aliceContactId));
|
||||
read(bob, aliceContactId, write(alice, bobContactId));
|
||||
read(alice, bobContactId, write(bob, aliceContactId));
|
||||
read(bob, aliceContactId, write(alice, bobContactId));
|
||||
read(alice, bobContactId, write(bob, aliceContactId));
|
||||
read(bob, aliceContactId, write(alice, bobContactId));
|
||||
read(alice, bobContactId, write(bob, aliceContactId));
|
||||
|
||||
sendMessage(bob, aliceContactId);
|
||||
read(alice, bobContactId, write(bob, aliceContactId));
|
||||
|
||||
onView(isRoot())
|
||||
.perform(waitUntilMatches(withText(bobAuthor.getName())));
|
||||
onView(withId(R.id.recyclerView))
|
||||
.perform(actionOnItemAtPosition(0, click()));
|
||||
onView(isRoot())
|
||||
.perform(waitUntilMatches(withText(R.string.screenshot_message_2)));
|
||||
|
||||
assertEquals(1,
|
||||
alice.conversationManager().getGroupCount(bobContactId).getMsgCount());
|
||||
|
||||
Thread.sleep(5000);
|
||||
}
|
||||
|
||||
private void sendMessage(FakeDataTestComponent device, ContactId contactId)
|
||||
throws Exception {
|
||||
// Send Bob a message
|
||||
MessagingManager messagingManager = device.getMessagingManager();
|
||||
GroupId groupId = messagingManager.getConversationId(contactId);
|
||||
PrivateMessageFactory privateMessageFactory =
|
||||
device.getPrivateMessageFactory();
|
||||
PrivateMessage message = privateMessageFactory.createPrivateMessage(
|
||||
groupId, getMinutesAgo(3),
|
||||
getTargetContext().getString(R.string.screenshot_message_2));
|
||||
messagingManager.addLocalMessage(message);
|
||||
}
|
||||
|
||||
private void read(FakeDataTestComponent device,
|
||||
ContactId contactId, byte[] stream) throws Exception {
|
||||
// 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);
|
||||
KeyManager keyManager = device.getKeyManager();
|
||||
StreamContext ctx = keyManager.getStreamContext(TRANSPORT_ID, tag);
|
||||
assertNotNull(ctx);
|
||||
// Create a stream reader
|
||||
StreamReaderFactory streamReaderFactory =
|
||||
device.getStreamReaderFactory();
|
||||
InputStream streamReader = streamReaderFactory.createStreamReader(
|
||||
in, ctx);
|
||||
// Create an incoming sync session
|
||||
SyncSessionFactory syncSessionFactory = device.getSyncSessionFactory();
|
||||
SyncSession session = syncSessionFactory.createIncomingSession(
|
||||
contactId, streamReader);
|
||||
// Read whatever needs to be read
|
||||
session.run();
|
||||
streamReader.close();
|
||||
}
|
||||
|
||||
private byte[] write(FakeDataTestComponent device,
|
||||
ContactId contactId) throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
// Get a stream context
|
||||
KeyManager keyManager = device.getKeyManager();
|
||||
StreamContext ctx = keyManager.getStreamContext(contactId,
|
||||
TRANSPORT_ID);
|
||||
assertNotNull(ctx);
|
||||
// Create a stream writer
|
||||
StreamWriterFactory streamWriterFactory =
|
||||
device.getStreamWriterFactory();
|
||||
StreamWriter streamWriter =
|
||||
streamWriterFactory.createStreamWriter(out, ctx);
|
||||
// Create an outgoing sync session
|
||||
SyncSessionFactory syncSessionFactory = device.getSyncSessionFactory();
|
||||
SyncSession session = syncSessionFactory.createSimplexOutgoingSession(
|
||||
contactId, MAX_LATENCY, streamWriter);
|
||||
// Write whatever needs to be written
|
||||
session.run();
|
||||
streamWriter.sendEndOfStream();
|
||||
// Return the contents of the stream
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private void createTestDataExceptions()
|
||||
throws DbException, FormatException {
|
||||
String bobName =
|
||||
getTargetContext().getString(R.string.screenshot_bob);
|
||||
Contact bob = testDataCreator.addContact(bobName);
|
||||
|
||||
String bobHi = getTargetContext()
|
||||
.getString(R.string.screenshot_message_1);
|
||||
long bobTime = getMinutesAgo(2);
|
||||
testDataCreator.addPrivateMessage(bob, bobHi, bobTime, true);
|
||||
|
||||
String aliceHi = getTargetContext()
|
||||
.getString(R.string.screenshot_message_2);
|
||||
long aliceTime = getMinutesAgo(1);
|
||||
testDataCreator.addPrivateMessage(bob, aliceHi, aliceTime, false);
|
||||
|
||||
String bobHi2 = getTargetContext()
|
||||
.getString(R.string.screenshot_message_3);
|
||||
long bobTime2 = getMinutesAgo(0);
|
||||
testDataCreator.addPrivateMessage(bob, bobHi2, bobTime2, true);
|
||||
|
||||
connectionRegistry.registerConnection(bob.getId(), ID, true);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.StrictMode;
|
||||
|
||||
import com.vanniktech.emoji.RecentEmoji;
|
||||
|
||||
import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.reporting.DevConfig;
|
||||
import org.briarproject.bramble.util.AndroidUtils;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.briarproject.briar.android.account.LockManagerImpl;
|
||||
import org.briarproject.briar.api.android.AndroidNotificationManager;
|
||||
import org.briarproject.briar.api.android.DozeWatchdog;
|
||||
import org.briarproject.briar.api.android.LockManager;
|
||||
import org.briarproject.briar.api.android.ScreenFilterMonitor;
|
||||
|
||||
import java.io.File;
|
||||
import java.security.GeneralSecurityException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_ONION_ADDRESS;
|
||||
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_PUBLIC_KEY_HEX;
|
||||
|
||||
@Module(includes = TestPluginConfigModule.class)
|
||||
public class TestAppModule {
|
||||
|
||||
static class EagerSingletons {
|
||||
@Inject
|
||||
AndroidNotificationManager androidNotificationManager;
|
||||
@Inject
|
||||
NetworkUsageLogger networkUsageLogger;
|
||||
@Inject
|
||||
DozeWatchdog dozeWatchdog;
|
||||
@Inject
|
||||
RecentEmoji recentEmoji;
|
||||
}
|
||||
|
||||
private final Application application;
|
||||
|
||||
public TestAppModule(Application application) {
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
Application providesApplication() {
|
||||
return application;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
DatabaseConfig provideDatabaseConfig(Application app) {
|
||||
//FIXME: StrictMode
|
||||
StrictMode.ThreadPolicy tp = StrictMode.allowThreadDiskReads();
|
||||
StrictMode.allowThreadDiskWrites();
|
||||
File dbDir = app.getApplicationContext().getDir("db", MODE_PRIVATE);
|
||||
File keyDir = app.getApplicationContext().getDir("key", MODE_PRIVATE);
|
||||
StrictMode.setThreadPolicy(tp);
|
||||
return new AndroidDatabaseConfig(dbDir, keyDir);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
DevConfig provideDevConfig(Application app, CryptoComponent crypto) {
|
||||
@NotNullByDefault
|
||||
DevConfig devConfig = new DevConfig() {
|
||||
|
||||
@Override
|
||||
public PublicKey getDevPublicKey() {
|
||||
try {
|
||||
return crypto.getMessageKeyParser().parsePublicKey(
|
||||
StringUtils.fromHexString(DEV_PUBLIC_KEY_HEX));
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDevOnionAddress() {
|
||||
return DEV_ONION_ADDRESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getReportDir() {
|
||||
return AndroidUtils.getReportDir(app.getApplicationContext());
|
||||
}
|
||||
};
|
||||
return devConfig;
|
||||
}
|
||||
|
||||
@Provides
|
||||
SharedPreferences provideSharedPreferences(Application app) {
|
||||
// FIXME unify this with getDefaultSharedPreferences()
|
||||
return app.getSharedPreferences("db", MODE_PRIVATE);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
AndroidNotificationManager provideAndroidNotificationManager(
|
||||
LifecycleManager lifecycleManager, EventBus eventBus,
|
||||
AndroidNotificationManagerImpl notificationManager) {
|
||||
lifecycleManager.registerService(notificationManager);
|
||||
eventBus.addListener(notificationManager);
|
||||
return notificationManager;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
ScreenFilterMonitor provideScreenFilterMonitor(
|
||||
LifecycleManager lifecycleManager,
|
||||
ScreenFilterMonitorImpl screenFilterMonitor) {
|
||||
lifecycleManager.registerService(screenFilterMonitor);
|
||||
return screenFilterMonitor;
|
||||
}
|
||||
|
||||
@Provides
|
||||
NetworkUsageLogger provideNetworkUsageLogger(
|
||||
LifecycleManager lifecycleManager) {
|
||||
NetworkUsageLogger networkUsageLogger = new NetworkUsageLogger();
|
||||
lifecycleManager.registerService(networkUsageLogger);
|
||||
return networkUsageLogger;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
DozeWatchdog provideDozeWatchdog(LifecycleManager lifecycleManager) {
|
||||
DozeWatchdogImpl dozeWatchdog = new DozeWatchdogImpl(application);
|
||||
lifecycleManager.registerService(dozeWatchdog);
|
||||
return dozeWatchdog;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
LockManager provideLockManager(LifecycleManager lifecycleManager,
|
||||
EventBus eventBus, LockManagerImpl lockManager) {
|
||||
lifecycleManager.registerService(lockManager);
|
||||
eventBus.addListener(lockManager);
|
||||
return lockManager;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
RecentEmoji provideRecentEmoji(LifecycleManager lifecycleManager,
|
||||
RecentEmojiImpl recentEmoji) {
|
||||
lifecycleManager.registerClient(recentEmoji);
|
||||
return recentEmoji;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.PluginConfig;
|
||||
import org.briarproject.bramble.api.plugin.TransportId;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
|
||||
import org.briarproject.bramble.api.plugin.simplex.SimplexPlugin;
|
||||
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginCallback;
|
||||
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.briarproject.bramble.test.TestUtils.getTransportId;
|
||||
|
||||
@Module
|
||||
public class TestPluginConfigModule {
|
||||
|
||||
public static final TransportId TRANSPORT_ID = getTransportId();
|
||||
public static final int MAX_LATENCY = 2 * 60 * 1000; // 2 minutes
|
||||
|
||||
@NotNullByDefault
|
||||
private final SimplexPluginFactory simplex = new SimplexPluginFactory() {
|
||||
|
||||
@Override
|
||||
public TransportId getId() {
|
||||
return TRANSPORT_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxLatency() {
|
||||
return MAX_LATENCY;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public SimplexPlugin createPlugin(SimplexPluginCallback callback) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
@Provides
|
||||
PluginConfig providePluginConfig() {
|
||||
@NotNullByDefault
|
||||
PluginConfig pluginConfig = new PluginConfig() {
|
||||
|
||||
@Override
|
||||
public Collection<DuplexPluginFactory> getDuplexFactories() {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SimplexPluginFactory> getSimplexFactories() {
|
||||
return singletonList(simplex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldPoll() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
return pluginConfig;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.briarproject.briar.android.contact;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.test.rule.ActivityTestRule;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.BriarUiTestComponent;
|
||||
import org.briarproject.briar.android.ScreenshotTest;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static android.support.test.InstrumentationRegistry.getInstrumentation;
|
||||
import static android.support.test.espresso.Espresso.onView;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static org.briarproject.briar.android.ViewActions.waitUntilMatches;
|
||||
import static org.briarproject.briar.android.contact.ConversationActivity.CONTACT_ID;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ConversationActivityScreenshotTest extends ScreenshotTest {
|
||||
|
||||
@Rule
|
||||
public ActivityTestRule<ConversationActivity> testRule =
|
||||
new ActivityTestRule<>(ConversationActivity.class, false, false);
|
||||
|
||||
@Override
|
||||
protected void inject(BriarUiTestComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void messaging() throws Exception {
|
||||
Context targetContext = getInstrumentation().getTargetContext();
|
||||
Intent intent = new Intent(targetContext, ConversationActivity.class);
|
||||
intent.putExtra(CONTACT_ID, 1);
|
||||
testRule.launchActivity(intent);
|
||||
|
||||
onView(withId(R.id.conversationView))
|
||||
.perform(waitUntilMatches(allOf(
|
||||
withText(R.string.screenshot_message_3),
|
||||
isCompletelyDisplayed())
|
||||
));
|
||||
|
||||
screenshot("manual_messaging", testRule.getActivity());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,14 +2,15 @@ package org.briarproject.briar.android.settings;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.support.test.espresso.contrib.DrawerActions;
|
||||
import android.support.test.rule.ActivityTestRule;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.Gravity;
|
||||
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.BriarUiTestComponent;
|
||||
import org.briarproject.briar.android.ScreenshotTest;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
||||
import org.briarproject.briar.android.test.ScreenshotTest;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -26,15 +27,15 @@ import static android.support.test.espresso.matcher.ViewMatchers.withChild;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withClassName;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static org.briarproject.briar.android.test.ViewActions.waitUntilMatches;
|
||||
import static org.briarproject.briar.android.ViewActions.waitUntilMatches;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class SettingsActivityScreenshotTest extends ScreenshotTest {
|
||||
|
||||
@Rule
|
||||
public CleanAccountTestRule<SettingsActivity> testRule =
|
||||
new CleanAccountTestRule<>(SettingsActivity.class);
|
||||
public ActivityTestRule<SettingsActivity> testRule =
|
||||
new ActivityTestRule<>(SettingsActivity.class);
|
||||
|
||||
@Override
|
||||
protected void inject(BriarUiTestComponent component) {
|
||||
@@ -46,7 +47,7 @@ public class SettingsActivityScreenshotTest extends ScreenshotTest {
|
||||
onView(withText(R.string.settings_button))
|
||||
.check(matches(isDisplayed()));
|
||||
|
||||
screenshot("manual_dark_theme_settings");
|
||||
screenshot("manual_dark_theme_settings", testRule.getActivity());
|
||||
|
||||
// switch to dark theme
|
||||
onView(withText(R.string.pref_theme_title))
|
||||
@@ -56,10 +57,20 @@ public class SettingsActivityScreenshotTest extends ScreenshotTest {
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(click());
|
||||
|
||||
// open nav drawer and remove expiry warning
|
||||
openNavDrawer(true);
|
||||
openNavDrawer();
|
||||
|
||||
screenshot("manual_dark_theme_nav_drawer");
|
||||
screenshot("manual_dark_theme_nav_drawer", testRule.getActivity());
|
||||
|
||||
// switch to back to light theme
|
||||
onView(withText(R.string.settings_button))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(click());
|
||||
onView(withText(R.string.pref_theme_title))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(click());
|
||||
onView(withText(R.string.pref_theme_light))
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(click());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -83,12 +94,11 @@ public class SettingsActivityScreenshotTest extends ScreenshotTest {
|
||||
.check(matches(isDisplayed()))
|
||||
.check(matches(isEnabled()));
|
||||
|
||||
screenshot("manual_app_lock");
|
||||
screenshot("manual_app_lock", testRule.getActivity());
|
||||
|
||||
// no more expiry warning to remove, because sharedprefs cached?
|
||||
openNavDrawer(false);
|
||||
openNavDrawer();
|
||||
|
||||
screenshot("manual_app_lock_nav_drawer");
|
||||
screenshot("manual_app_lock_nav_drawer", testRule.getActivity());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -104,23 +114,15 @@ public class SettingsActivityScreenshotTest extends ScreenshotTest {
|
||||
.check(matches(isDisplayed()))
|
||||
.perform(waitUntilMatches(isEnabled()));
|
||||
|
||||
screenshot("manual_tor_settings");
|
||||
screenshot("manual_tor_settings", testRule.getActivity());
|
||||
}
|
||||
|
||||
private void openNavDrawer(boolean expiry) {
|
||||
private void openNavDrawer() {
|
||||
// start main activity
|
||||
Intent i =
|
||||
new Intent(testRule.getActivity(), NavDrawerActivity.class);
|
||||
testRule.getActivity().startActivity(i);
|
||||
|
||||
// close expiry warning
|
||||
if (expiry) {
|
||||
onView(withId(R.id.expiryWarningClose))
|
||||
.check(matches(isDisplayed()));
|
||||
onView(withId(R.id.expiryWarningClose))
|
||||
.perform(click());
|
||||
}
|
||||
|
||||
// open navigation drawer
|
||||
onView(withId(R.id.drawer_layout))
|
||||
.check(matches(isClosed(Gravity.START)))
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.StrictMode;
|
||||
|
||||
@@ -11,24 +10,9 @@ import org.briarproject.bramble.api.crypto.CryptoComponent;
|
||||
import org.briarproject.bramble.api.crypto.PublicKey;
|
||||
import org.briarproject.bramble.api.db.DatabaseConfig;
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.bramble.api.network.NetworkManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.BackoffFactory;
|
||||
import org.briarproject.bramble.api.plugin.PluginConfig;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
|
||||
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
|
||||
import org.briarproject.bramble.api.reporting.DevConfig;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.system.LocationUtils;
|
||||
import org.briarproject.bramble.api.system.ResourceProvider;
|
||||
import org.briarproject.bramble.api.system.Scheduler;
|
||||
import org.briarproject.bramble.plugin.bluetooth.AndroidBluetoothPluginFactory;
|
||||
import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory;
|
||||
import org.briarproject.bramble.plugin.tor.AndroidTorPluginFactory;
|
||||
import org.briarproject.bramble.plugin.tor.CircumventionProvider;
|
||||
import org.briarproject.bramble.util.AndroidUtils;
|
||||
import org.briarproject.bramble.util.StringUtils;
|
||||
import org.briarproject.briar.android.account.LockManagerImpl;
|
||||
@@ -39,25 +23,18 @@ import org.briarproject.briar.api.android.ScreenFilterMonitor;
|
||||
|
||||
import java.io.File;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
import static android.content.Context.MODE_PRIVATE;
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_ONION_ADDRESS;
|
||||
import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_PUBLIC_KEY_HEX;
|
||||
|
||||
@Module
|
||||
@Module(includes = PluginConfigModule.class)
|
||||
public class AppModule {
|
||||
|
||||
static class EagerSingletons {
|
||||
@@ -95,47 +72,6 @@ public class AppModule {
|
||||
return new AndroidDatabaseConfig(dbDir, keyDir);
|
||||
}
|
||||
|
||||
@Provides
|
||||
PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor,
|
||||
@Scheduler ScheduledExecutorService scheduler,
|
||||
AndroidExecutor androidExecutor, SecureRandom random,
|
||||
SocketFactory torSocketFactory, BackoffFactory backoffFactory,
|
||||
Application app, NetworkManager networkManager,
|
||||
LocationUtils locationUtils, EventBus eventBus,
|
||||
ResourceProvider resourceProvider,
|
||||
CircumventionProvider circumventionProvider, Clock clock) {
|
||||
Context appContext = app.getApplicationContext();
|
||||
DuplexPluginFactory bluetooth =
|
||||
new AndroidBluetoothPluginFactory(ioExecutor, androidExecutor,
|
||||
appContext, random, eventBus, backoffFactory);
|
||||
DuplexPluginFactory tor = new AndroidTorPluginFactory(ioExecutor,
|
||||
scheduler, appContext, networkManager, locationUtils, eventBus,
|
||||
torSocketFactory, backoffFactory, resourceProvider,
|
||||
circumventionProvider, clock);
|
||||
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
|
||||
eventBus, backoffFactory, appContext);
|
||||
Collection<DuplexPluginFactory> duplex = asList(bluetooth, tor, lan);
|
||||
@NotNullByDefault
|
||||
PluginConfig pluginConfig = new PluginConfig() {
|
||||
|
||||
@Override
|
||||
public Collection<DuplexPluginFactory> getDuplexFactories() {
|
||||
return duplex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SimplexPluginFactory> getSimplexFactories() {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldPoll() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
return pluginConfig;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
DevConfig provideDevConfig(Application app, CryptoComponent crypto) {
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
package org.briarproject.briar.android;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import org.briarproject.bramble.api.event.EventBus;
|
||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||
import org.briarproject.bramble.api.network.NetworkManager;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.BackoffFactory;
|
||||
import org.briarproject.bramble.api.plugin.PluginConfig;
|
||||
import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory;
|
||||
import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory;
|
||||
import org.briarproject.bramble.api.system.AndroidExecutor;
|
||||
import org.briarproject.bramble.api.system.Clock;
|
||||
import org.briarproject.bramble.api.system.LocationUtils;
|
||||
import org.briarproject.bramble.api.system.ResourceProvider;
|
||||
import org.briarproject.bramble.api.system.Scheduler;
|
||||
import org.briarproject.bramble.plugin.bluetooth.AndroidBluetoothPluginFactory;
|
||||
import org.briarproject.bramble.plugin.tcp.AndroidLanTcpPluginFactory;
|
||||
import org.briarproject.bramble.plugin.tor.AndroidTorPluginFactory;
|
||||
import org.briarproject.bramble.plugin.tor.CircumventionProvider;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
@Module
|
||||
public class PluginConfigModule {
|
||||
|
||||
@Provides
|
||||
PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor,
|
||||
@Scheduler ScheduledExecutorService scheduler,
|
||||
AndroidExecutor androidExecutor, SecureRandom random,
|
||||
SocketFactory torSocketFactory, BackoffFactory backoffFactory,
|
||||
Application app, NetworkManager networkManager,
|
||||
LocationUtils locationUtils, EventBus eventBus,
|
||||
ResourceProvider resourceProvider,
|
||||
CircumventionProvider circumventionProvider, Clock clock) {
|
||||
Context appContext = app.getApplicationContext();
|
||||
DuplexPluginFactory bluetooth =
|
||||
new AndroidBluetoothPluginFactory(ioExecutor, androidExecutor,
|
||||
appContext, random, eventBus, backoffFactory);
|
||||
DuplexPluginFactory tor = new AndroidTorPluginFactory(ioExecutor,
|
||||
scheduler, appContext, networkManager, locationUtils, eventBus,
|
||||
torSocketFactory, backoffFactory, resourceProvider,
|
||||
circumventionProvider, clock);
|
||||
DuplexPluginFactory lan = new AndroidLanTcpPluginFactory(ioExecutor,
|
||||
eventBus, backoffFactory, appContext);
|
||||
Collection<DuplexPluginFactory> duplex = asList(bluetooth, tor, lan);
|
||||
@NotNullByDefault
|
||||
PluginConfig pluginConfig = new PluginConfig() {
|
||||
|
||||
@Override
|
||||
public Collection<DuplexPluginFactory> getDuplexFactories() {
|
||||
return duplex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<SimplexPluginFactory> getSimplexFactories() {
|
||||
return emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldPoll() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
return pluginConfig;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -480,4 +480,20 @@
|
||||
<string name="lock_is_locked">Briar is locked</string>
|
||||
<string name="lock_tap_to_unlock">Tap to unlock</string>
|
||||
|
||||
<!-- Screenshots -->
|
||||
|
||||
<!-- This is a name to be used in screenshots. Feel free to change it to a local name. -->
|
||||
<string name="screenshot_alice">Alice</string>
|
||||
<!-- This is a name to be used in screenshots. Feel free to change it to a local name. -->
|
||||
<string name="screenshot_bob">Bob</string>
|
||||
<!-- This is a name to be used in screenshots. Feel free to change it to a local name. -->
|
||||
<string name="screenshot_carol">Carol</string>
|
||||
<!-- This is a message to be used in screenshots. Please use the same translation for Bob! -->
|
||||
<string name="screenshot_message_1">Hi Bob!</string>
|
||||
<!-- This is a message to be used in screenshots. Please use the same translation for Alice! -->
|
||||
<string name="screenshot_message_2">Hi Alice! Thanks for telling me about Briar!</string>
|
||||
<!-- This is a message to be used in screenshots. -->
|
||||
<string name="screenshot_message_3">No problem, hope you like it 😀</string>
|
||||
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -82,6 +82,7 @@ dependencyVerification {
|
||||
'com.google.zxing:core:3.3.0:core-3.3.0.jar:bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d',
|
||||
'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
|
||||
'com.ibm.icu:icu4j:53.1:icu4j-53.1.jar:e37a4467bac5cdeb02c5c4b8e5063d2f4e67b69e3c7df6d6b610f13185572bab',
|
||||
'com.jraska:falcon:1.0.4:falcon-1.0.4.aar:6114a48d8b3814f75fc69b5e84dc087c1254883874eae8a36bd778979800630a',
|
||||
'com.squareup:javawriter:2.1.1:javawriter-2.1.1.jar:f699823d0081f69cbb676c1845ea222e0ada79bc88a53e5d22d8bd02d328f57e',
|
||||
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
|
||||
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
|
||||
@@ -171,7 +172,7 @@ dependencyVerification {
|
||||
'org.robolectric:shadows-framework:3.8:shadows-framework-3.8.jar:83548db7249edf1af87e1a1f4d8f4eec3e85d6220161da601e6f6398476911b2',
|
||||
'org.robolectric:shadows-support-v4:3.3.2:shadows-support-v4-3.3.2.jar:6f689264738266e70fe08db7c04b7b5a75155994f4e3f7f311960d90486bf005',
|
||||
'org.robolectric:utils:3.8:utils-3.8.jar:e945d04d40e37554e02d4be1bc3abf9bede45375c843aa36d10ccb6b63edbf34',
|
||||
'tools.fastlane:screengrab:1.1.0:screengrab-1.1.0.aar:03ce3868ee8a0082d14e7a1de0999f91531c0cc794392688beb08ee9bc4495fd',
|
||||
'tools.fastlane:screengrab:1.2.0:screengrab-1.2.0.aar:af4ee23bb06f94404d3ab18e2ea69db8265539fc8da29f9ee45b7e472684ba83',
|
||||
'uk.co.samuelwall:material-tap-target-prompt:2.8.0:material-tap-target-prompt-2.8.0.aar:ac70770c05bbc4675a1d5712c0e53d46ee4fa961b74947589fce50d8003065ec',
|
||||
'xmlpull:xmlpull:1.1.3.1:xmlpull-1.1.3.1.jar:34e08ee62116071cbb69c0ed70d15a7a5b208d62798c59f2120bb8929324cb63',
|
||||
'xpp3:xpp3_min:1.1.4c:xpp3_min-1.1.4c.jar:bfc90e9e32d0eab1f397fb974b5f150a815188382ac41f372a7149d5bc178008',
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
package org.briarproject.briar.api.test;
|
||||
|
||||
import org.briarproject.bramble.api.FormatException;
|
||||
import org.briarproject.bramble.api.contact.Contact;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface TestDataCreator {
|
||||
|
||||
/**
|
||||
* Create fake test data on the DatabaseExecutor
|
||||
* Create fake test data on the IoExecutor
|
||||
*
|
||||
* @param numContacts Number of contacts to create. Must be >= 1
|
||||
* @param numPrivateMsgs Number of private messages to create for each
|
||||
@@ -18,4 +22,11 @@ public interface TestDataCreator {
|
||||
void createTestData(int numContacts, int numPrivateMsgs, int numBlogPosts,
|
||||
int numForums, int numForumPosts);
|
||||
|
||||
@IoExecutor
|
||||
Contact addContact(String name) throws DbException;
|
||||
|
||||
@IoExecutor
|
||||
void addPrivateMessage(Contact contact, String body, long time,
|
||||
boolean local) throws DbException, FormatException;
|
||||
|
||||
}
|
||||
|
||||
@@ -13,9 +13,11 @@ import org.briarproject.bramble.api.db.DatabaseComponent;
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.bramble.api.db.Transaction;
|
||||
import org.briarproject.bramble.api.identity.AuthorFactory;
|
||||
import org.briarproject.bramble.api.identity.AuthorId;
|
||||
import org.briarproject.bramble.api.identity.IdentityManager;
|
||||
import org.briarproject.bramble.api.identity.LocalAuthor;
|
||||
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.bramble.api.plugin.BluetoothConstants;
|
||||
import org.briarproject.bramble.api.plugin.LanTcpConstants;
|
||||
import org.briarproject.bramble.api.plugin.TorConstants;
|
||||
@@ -59,6 +61,7 @@ import static org.briarproject.bramble.util.StringUtils.getRandomString;
|
||||
import static org.briarproject.briar.test.TestData.AUTHOR_NAMES;
|
||||
import static org.briarproject.briar.test.TestData.GROUP_NAMES;
|
||||
|
||||
@NotNullByDefault
|
||||
public class TestDataCreatorImpl implements TestDataCreator {
|
||||
|
||||
private final Logger LOG =
|
||||
@@ -147,17 +150,17 @@ public class TestDataCreatorImpl implements TestDataCreator {
|
||||
List<Contact> contacts = new ArrayList<>(numContacts);
|
||||
LocalAuthor localAuthor = identityManager.getLocalAuthor();
|
||||
for (int i = 0; i < numContacts; i++) {
|
||||
Contact contact = addRandomContact(localAuthor);
|
||||
LocalAuthor author = getRandomAuthor();
|
||||
Contact contact = addContact(localAuthor.getId(), author);
|
||||
contacts.add(contact);
|
||||
}
|
||||
return contacts;
|
||||
}
|
||||
|
||||
private Contact addRandomContact(LocalAuthor localAuthor)
|
||||
private Contact addContact(AuthorId localAuthorId, LocalAuthor author)
|
||||
throws DbException {
|
||||
|
||||
// prepare to add contact
|
||||
LocalAuthor author = getRandomAuthor();
|
||||
SecretKey secretKey = getSecretKey();
|
||||
long timestamp = clock.currentTimeMillis();
|
||||
boolean verified = random.nextBoolean();
|
||||
@@ -170,7 +173,7 @@ public class TestDataCreatorImpl implements TestDataCreator {
|
||||
Transaction txn = db.startTransaction(false);
|
||||
try {
|
||||
ContactId contactId = contactManager
|
||||
.addContact(txn, author, localAuthor.getId(), secretKey,
|
||||
.addContact(txn, author, localAuthorId, secretKey,
|
||||
timestamp, true, verified, true);
|
||||
transportPropertyManager.addRemoteProperties(txn, contactId, props);
|
||||
contact = db.getContact(txn, contactId);
|
||||
@@ -187,14 +190,23 @@ public class TestDataCreatorImpl implements TestDataCreator {
|
||||
return contact;
|
||||
}
|
||||
|
||||
private LocalAuthor getRandomAuthor() {
|
||||
int i = random.nextInt(AUTHOR_NAMES.length);
|
||||
String authorName = AUTHOR_NAMES[i];
|
||||
@Override
|
||||
public Contact addContact(String name) throws DbException {
|
||||
LocalAuthor localAuthor = identityManager.getLocalAuthor();
|
||||
return addContact(localAuthor.getId(), getAuthor(name));
|
||||
}
|
||||
|
||||
private LocalAuthor getAuthor(String name) {
|
||||
KeyPair keyPair = cryptoComponent.generateSignatureKeyPair();
|
||||
byte[] publicKey = keyPair.getPublic().getEncoded();
|
||||
byte[] privateKey = keyPair.getPrivate().getEncoded();
|
||||
return authorFactory.createLocalAuthor(authorName, publicKey,
|
||||
privateKey);
|
||||
return authorFactory.createLocalAuthor(name, publicKey, privateKey);
|
||||
}
|
||||
|
||||
private LocalAuthor getRandomAuthor() {
|
||||
int i = random.nextInt(AUTHOR_NAMES.length);
|
||||
String authorName = AUTHOR_NAMES[i];
|
||||
return getAuthor(authorName);
|
||||
}
|
||||
|
||||
private SecretKey getSecretKey() {
|
||||
@@ -286,7 +298,7 @@ public class TestDataCreatorImpl implements TestDataCreator {
|
||||
Group group = messagingManager.getContactGroup(contact);
|
||||
for (int i = 0; i < numPrivateMsgs; i++) {
|
||||
try {
|
||||
createPrivateMessage(group.getId(), i);
|
||||
createRandomPrivateMessage(group.getId(), i);
|
||||
} catch (FormatException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -298,14 +310,18 @@ public class TestDataCreatorImpl implements TestDataCreator {
|
||||
}
|
||||
}
|
||||
|
||||
private void createPrivateMessage(GroupId groupId, int num)
|
||||
private void createRandomPrivateMessage(GroupId groupId, int num)
|
||||
throws DbException, FormatException {
|
||||
long timestamp = clock.currentTimeMillis() - num * 60 * 1000;
|
||||
String body = getRandomText();
|
||||
boolean local = random.nextBoolean();
|
||||
createPrivateMessage(groupId, body, timestamp, local);
|
||||
}
|
||||
|
||||
private void createPrivateMessage(GroupId groupId, String body,
|
||||
long timestamp, boolean local) throws DbException, FormatException {
|
||||
PrivateMessage m = privateMessageFactory
|
||||
.createPrivateMessage(groupId, timestamp, body);
|
||||
|
||||
boolean local = random.nextBoolean();
|
||||
BdfDictionary meta = new BdfDictionary();
|
||||
meta.put("timestamp", timestamp);
|
||||
meta.put("local", local);
|
||||
@@ -322,6 +338,13 @@ public class TestDataCreatorImpl implements TestDataCreator {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPrivateMessage(Contact contact, String body, long time,
|
||||
boolean local) throws DbException, FormatException {
|
||||
Group group = messagingManager.getContactGroup(contact);
|
||||
createPrivateMessage(group.getId(), body, time, local);
|
||||
}
|
||||
|
||||
private void createBlogPosts(List<Contact> contacts, int numBlogPosts)
|
||||
throws DbException {
|
||||
for (int i = 0; i < numBlogPosts; i++) {
|
||||
|
||||
Reference in New Issue
Block a user