diff --git a/OpenKeychain/build.gradle b/OpenKeychain/build.gradle index 6a2cb0e0c..3ea7e058d 100644 --- a/OpenKeychain/build.gradle +++ b/OpenKeychain/build.gradle @@ -75,22 +75,6 @@ dependencies { } testImplementation 'org.mockito:mockito-core:2.18.0' - // UI testing with Espresso - // Force usage of support libs in the test app, since they are internally used by the runner module. - // https://github.com/googlesamples/android-testing/blob/master/ui/espresso/BasicSample/app/build.gradle#L28 - androidTestImplementation 'androidx.annotation:annotation:1.1.0' - androidTestImplementation 'androidx.appcompat:appcompat:1.1.0' - androidTestImplementation 'com.google.android.material:material:1.1.0' - androidTestImplementation 'androidx.test.ext:junit:1.1.1' - androidTestImplementation 'androidx.test:rules:1.2.0' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' - androidTestImplementation 'androidx.test.espresso:espresso-intents:3.2.0' - androidTestCompile ('androidx.test.espresso:espresso-contrib:3.1.0') { - exclude group: 'com.android.support', module: 'appcompat' - exclude group: 'com.android.support', module: 'support-v4' - exclude module: 'recyclerview-v7' - } - implementation 'com.jakewharton.timber:timber:4.7.1' implementation 'org.glassfish:javax.annotation:10.0-b28' diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/AndroidTestHelpers.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/AndroidTestHelpers.java deleted file mode 100644 index b2b7116da..000000000 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/AndroidTestHelpers.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2015 Vincent Breitmoser - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain; - - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Random; - -import android.content.Context; -import androidx.annotation.StringRes; -import androidx.test.espresso.UiController; -import androidx.test.espresso.ViewAction; -import androidx.test.espresso.matcher.ViewMatchers; -import android.view.View; - -import com.nispok.snackbar.Snackbar; -import org.hamcrest.Matcher; -import org.sufficientlysecure.keychain.pgp.UncachedKeyRing; -import org.sufficientlysecure.keychain.pgp.UncachedKeyRing.IteratorWithIOThrow; -import org.sufficientlysecure.keychain.daos.KeyWritableRepository; -import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.ui.util.Notify.Style; - -import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; -import static androidx.test.espresso.matcher.ViewMatchers.withClassName; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.CoreMatchers.endsWith; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withSnackbarLineColor; - - -public class AndroidTestHelpers { - - public static void dismissSnackbar() { - onView(withClassName(endsWith("Snackbar"))) - .perform(new ViewAction() { - @Override - public Matcher getConstraints() { - return ViewMatchers.isAssignableFrom(Snackbar.class); - } - - @Override - public String getDescription() { - return "dismiss snackbar"; - } - - @Override - public void perform(UiController uiController, View view) { - ((Snackbar) view).dismiss(); - } - }); - } - - public static void checkSnackbar(Style style, @StringRes Integer text) { - - onView(withClassName(endsWith("Snackbar"))) - .check(matches(withSnackbarLineColor(style.mLineColor))); - - if (text != null) { - onView(withClassName(endsWith("Snackbar"))) - .check(matches(hasDescendant(withText(text)))); - } - - } - - public static void checkAndDismissSnackbar(Style style, @StringRes Integer text) { - checkSnackbar(style, text); - dismissSnackbar(); - } - - public static void importKeysFromResource(Context context, String name) throws Exception { - IteratorWithIOThrow stream = UncachedKeyRing.fromStream( - getInstrumentation().getContext().getAssets().open(name)); - - KeyWritableRepository helper = KeyWritableRepository.create(context); - while(stream.hasNext()) { - UncachedKeyRing ring = stream.next(); - if (ring.isSecret()) { - helper.saveSecretKeyRing(ring); - } else { - helper.savePublicKeyRing(ring); - } - } - - } - - public static void copyFiles() throws IOException { - File cacheDir = getInstrumentation().getTargetContext().getFilesDir(); - byte[] buf = new byte[256]; - for (String filename : FILES) { - File outFile = new File(cacheDir, filename); - if (outFile.exists()) { - continue; - } - InputStream in = new BufferedInputStream(getInstrumentation().getContext().getAssets().open(filename)); - OutputStream out = new BufferedOutputStream(new FileOutputStream(outFile)); - int len; - while( (len = in.read(buf)) > 0) { - out.write(buf, 0, len); - } - } - } - - public static final String[] FILES = new String[] { "pa.png", "re.png", "ci.png" }; - public static File[] getImageNames() { - File cacheDir = getInstrumentation().getTargetContext().getFilesDir(); - File[] ret = new File[FILES.length]; - for (int i = 0; i < ret.length; i++) { - ret[i] = new File(cacheDir, FILES[i]); - } - return ret; - } - - public static T pickRandom(T[] haystack) { - return haystack[new Random().nextInt(haystack.length)]; - } - - public static String randomString(int min, int max) { - String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789!@#$%^&*()-_="; - Random r = new Random(); - StringBuilder passbuilder = new StringBuilder(); - // 5% chance for an empty string - for(int i = 0, j = r.nextInt(max)+min; i < j; i++) { - passbuilder.append(chars.charAt(r.nextInt(chars.length()))); - } - return passbuilder.toString(); - } - - public static void cleanupForTests(Context context) throws Exception { - - // KeychainDatabase.getInstance(context).clearDatabase(); - - // import these two, make sure they're there - importKeysFromResource(context, "x.sec.asc"); - - // make sure no passphrases are cached - PassphraseCacheService.clearCachedPassphrases(context); - - } -} diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/JacocoWorkaroundJUnitRunner.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/JacocoWorkaroundJUnitRunner.java deleted file mode 100644 index 67e2b4b44..000000000 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/JacocoWorkaroundJUnitRunner.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.sufficientlysecure.keychain; - - -import java.lang.reflect.Method; - -import android.os.Bundle; -import androidx.test.runner.AndroidJUnitRunner; - - -public class JacocoWorkaroundJUnitRunner extends AndroidJUnitRunner { - static { - System.setProperty("jacoco-agent.destfile", "/data/data/" - + BuildConfig.APPLICATION_ID + "/coverage.ec"); - } - - @Override - public void finish(int resultCode, Bundle results) { - try { - Class rt = Class.forName("org.jacoco.agent.rt.RT"); - Method getAgent = rt.getMethod("getAgent"); - Method dump = getAgent.getReturnType().getMethod("dump", boolean.class); - Object agent = getAgent.invoke(null); - dump.invoke(agent, false); - } catch (Exception e) { - e.printStackTrace(); - } - super.finish(resultCode, results); - } -} \ No newline at end of file diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/actions/CustomActions.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/actions/CustomActions.java deleted file mode 100644 index 589b785c2..000000000 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/actions/CustomActions.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2015 Vincent Breitmoser - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package org.sufficientlysecure.keychain.actions; - - -import androidx.test.espresso.UiController; -import androidx.test.espresso.ViewAction; -import androidx.test.espresso.matcher.ViewMatchers; -import android.view.View; - -import com.tokenautocomplete.TokenCompleteTextView; -import org.hamcrest.Matcher; -import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing; -import org.sufficientlysecure.keychain.daos.KeyWritableRepository; - -import static androidx.test.platform.app.InstrumentationRegistry.getTargetContext; - - -public abstract class CustomActions { - - public static ViewAction tokenEncryptViewAddToken(long keyId) throws Exception { - CanonicalizedPublicKeyRing ring = - KeyWritableRepository.create(getTargetContext()).getCanonicalizedPublicKeyRing(keyId); - final Object item = new KeyAdapter.KeyItem(ring); - - return new ViewAction() { - @Override - public Matcher getConstraints() { - return ViewMatchers.isAssignableFrom(TokenCompleteTextView.class); - } - - @Override - public String getDescription() { - return "add completion token"; - } - - @Override - public void perform(UiController uiController, View view) { - ((TokenCompleteTextView) view).addObject(item); - } - }; - } - - public static ViewAction tokenViewAddToken(final Object item) { - return new ViewAction() { - @Override - public Matcher getConstraints() { - return ViewMatchers.isAssignableFrom(TokenCompleteTextView.class); - } - - @Override - public String getDescription() { - return "add completion token"; - } - - @Override - public void perform(UiController uiController, View view) { - ((TokenCompleteTextView) view).addObject(item); - } - }; - } - -} \ No newline at end of file diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/actions/OrientationChangeAction.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/actions/OrientationChangeAction.java deleted file mode 100644 index 0b0c63fa5..000000000 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/actions/OrientationChangeAction.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.sufficientlysecure.keychain.actions; - - -import java.util.Collection; - -import android.app.Activity; -import android.content.Context; -import android.content.ContextWrapper; -import android.content.pm.ActivityInfo; -import androidx.test.espresso.UiController; -import androidx.test.espresso.ViewAction; -import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry; -import androidx.test.runner.lifecycle.Stage; -import android.view.View; - -import org.hamcrest.Matcher; - -import static androidx.test.espresso.matcher.ViewMatchers.isRoot; - -public class OrientationChangeAction implements ViewAction { - private final int orientation; - - private OrientationChangeAction(int orientation) { - this.orientation = orientation; - } - - @Override - public Matcher getConstraints() { - return isRoot(); - } - - @Override - public String getDescription() { - return "change orientation to " + orientation; - } - - @Override - public void perform(UiController uiController, View view) { - uiController.loopMainThreadUntilIdle(); - - final Activity activity = findActivity(view.getContext()); - if (activity == null){ - throw new IllegalStateException("Could not find the current activity"); - } - - activity.setRequestedOrientation(orientation); - - Collection resumedActivities = ActivityLifecycleMonitorRegistry - .getInstance().getActivitiesInStage(Stage.RESUMED); - - if (resumedActivities.isEmpty()) { - throw new RuntimeException("Could not change orientation"); - } - } - - private static Activity findActivity(Context context) { - if (context == null) - return null; - else if (context instanceof Activity) - return (Activity) context; - else if (context instanceof ContextWrapper) - return findActivity(((ContextWrapper) context).getBaseContext()); - - return null; - } - - public static ViewAction orientationLandscape() { - return new OrientationChangeAction(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); - } - - public static ViewAction orientationPortrait() { - return new OrientationChangeAction(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); - } -} \ No newline at end of file diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/BitmapMatcher.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/BitmapMatcher.java deleted file mode 100644 index c08847065..000000000 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/BitmapMatcher.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2015 Vincent Breitmoser - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * From the droidcon anroid espresso repository. - * https://github.com/xrigau/droidcon-android-espresso/ - * - */ - -package org.sufficientlysecure.keychain.matcher; - - -import android.graphics.Bitmap; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.view.View; -import android.widget.ImageView; - -import org.hamcrest.Description; -import org.hamcrest.TypeSafeMatcher; - - -public class BitmapMatcher extends TypeSafeMatcher { - - private final Bitmap mBitmap; - - public BitmapMatcher(Bitmap bitmap) { - super(View.class); - mBitmap = bitmap; - } - - @Override - public boolean matchesSafely(View view) { - if ( !(view instanceof ImageView) ) { - return false; - } - Drawable drawable = ((ImageView) view).getDrawable(); - return drawable != null && (drawable instanceof BitmapDrawable) - && ((BitmapDrawable) drawable).getBitmap().sameAs(mBitmap); - } - - @Override - public void describeTo(Description description) { - description.appendText("with equivalent specified bitmap"); - } - - public static BitmapMatcher withBitmap(Bitmap bitmap) { - return new BitmapMatcher(bitmap); - } - -} diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/CustomMatchers.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/CustomMatchers.java deleted file mode 100644 index a80cf20ac..000000000 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/CustomMatchers.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2015 Vincent Breitmoser - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - -package org.sufficientlysecure.keychain.matcher; - - -import androidx.annotation.ColorRes; -import androidx.annotation.IdRes; -import androidx.test.espresso.matcher.BoundedMatcher; -import androidx.recyclerview.widget.RecyclerView; -import android.view.View; -import android.widget.ViewAnimator; - -import com.nispok.snackbar.Snackbar; - -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.sufficientlysecure.keychain.R; - -import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; -import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withParent; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.CoreMatchers.allOf; -import static org.hamcrest.CoreMatchers.not; -import static org.sufficientlysecure.keychain.matcher.DrawableMatcher.withDrawable; - - -public abstract class CustomMatchers { - - public static Matcher withDisplayedChild(final int child) { - return new BoundedMatcher(ViewAnimator.class) { - public void describeTo(Description description) { - description.appendText("with displayed child: " + child); - } - - @Override - public boolean matchesSafely(ViewAnimator viewAnimator) { - return viewAnimator.getDisplayedChild() == child; - } - }; - } - - public static Matcher withSnackbarLineColor(@ColorRes final int colorRes) { - return new BoundedMatcher(Snackbar.class) { - public void describeTo(Description description) { - description.appendText("with color resource id: " + colorRes); - } - - @Override - public boolean matchesSafely(Snackbar snackbar) { - return snackbar.getResources().getColor(colorRes) == snackbar.getLineColor(); - } - }; - } - - public static Matcher withKeyItemId(final long keyId) { - return new BoundedMatcher(KeyItem.class) { - @Override - public boolean matchesSafely(KeyItem item) { - return item.mKeyId == keyId; - } - - @Override - public void describeTo(Description description) { - description.appendText("with key id: " + keyId); - } - }; - } - - public static Matcher withKeyHolderId(final long keyId) { - return new BoundedMatcher(RecyclerView.ViewHolder.class) { - @Override - public void describeTo(Description description) { - description.appendText("with ViewHolder id: " + keyId); - } - - @Override - protected boolean matchesSafely(View item) { - return item.getItemId() == keyId; - } - }; - } - - public static Matcher withKeyToken(@ColorRes final long keyId) { - return new BoundedMatcher(EncryptKeyCompletionView.class) { - public void describeTo(Description description) { - description.appendText("with key id token: " + keyId); - } - - @Override - public boolean matchesSafely(EncryptKeyCompletionView tokenView) { - for (Object object : tokenView.getObjects()) { - if (object instanceof KeyItem && ((KeyItem) object).mKeyId == keyId) { - return true; - } - } - return false; - } - }; - } - - public static Matcher withRecyclerView(@IdRes int viewId) { - return allOf(isAssignableFrom(RecyclerView.class), withId(viewId)); - } - - public static Matcher isRecyclerItemView(@IdRes int recyclerId, Matcher specificChildMatcher) { - return allOf(withParent(withRecyclerView(recyclerId)), specificChildMatcher); - } - - public static Matcher withEncryptionStatus(boolean encrypted) { - - if (encrypted) { - return allOf( - hasDescendant(allOf( - withId(R.id.result_encryption_text), withText(R.string.decrypt_result_encrypted))), - hasDescendant(allOf( - withId(R.id.result_encryption_icon), withDrawable(R.drawable.status_lock_closed_24dp, true))) - ); - } else { - return allOf( - hasDescendant(allOf( - withId(R.id.result_encryption_text), withText(R.string.decrypt_result_not_encrypted))), - hasDescendant(allOf( - withId(R.id.result_encryption_icon), withDrawable(R.drawable.status_lock_open_24dp, true))) - ); - } - } - - public static Matcher withSignatureNone() { - - return allOf( - hasDescendant(allOf( - withId(R.id.result_signature_text), withText(R.string.decrypt_result_no_signature))), - hasDescendant(allOf( - withId(R.id.result_signature_icon), withDrawable(R.drawable.status_signature_invalid_cutout_24dp, true))), - hasDescendant(allOf( - withId(R.id.result_signature_layout), not(isDisplayed()))) - ); - - } - - public static Matcher withSignatureMyKey() { - - return allOf( - hasDescendant(allOf( - withId(R.id.result_signature_text), withText(R.string.decrypt_result_signature_certified))), - hasDescendant(allOf( - withId(R.id.result_signature_icon), withDrawable(R.drawable.status_signature_verified_cutout_24dp, true))), - hasDescendant(allOf( - withId(R.id.result_signature_layout), isDisplayed())) - ); - - } - -} diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/DrawableMatcher.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/DrawableMatcher.java deleted file mode 100644 index da2ff87d9..000000000 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/DrawableMatcher.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2015 Xavi Rigau - * Copyright (C) 2015 Vincent Breitmoser - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * From the droidcon anroid espresso repository. - * https://github.com/xrigau/droidcon-android-espresso/ - * - */ - -package org.sufficientlysecure.keychain.matcher; - - -import android.content.res.Resources; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; - -import org.hamcrest.Description; -import org.hamcrest.TypeSafeMatcher; - - -public class DrawableMatcher extends TypeSafeMatcher { - - private final int mResourceId; - private final boolean mIgnoreFilters; - - public DrawableMatcher(int resourceId, boolean ignoreFilters) { - super(View.class); - mResourceId = resourceId; - mIgnoreFilters = ignoreFilters; - } - - private String resourceName = null; - private Drawable expectedDrawable = null; - - @Override - public boolean matchesSafely(View target) { - if (expectedDrawable == null) { - loadDrawableFromResources(target.getResources()); - } - if (invalidExpectedDrawable()) { - return false; - } - - if (target instanceof ImageView) { - return hasImage((ImageView) target) || hasBackground(target); - } - if (target instanceof TextView) { - return hasCompoundDrawable((TextView) target) || hasBackground(target); - } - return hasBackground(target); - } - - private void loadDrawableFromResources(Resources resources) { - try { - expectedDrawable = resources.getDrawable(mResourceId); - resourceName = resources.getResourceEntryName(mResourceId); - } catch (Resources.NotFoundException ignored) { - // view could be from a context unaware of the resource id. - } - } - - private boolean invalidExpectedDrawable() { - return expectedDrawable == null; - } - - private boolean hasImage(ImageView target) { - return isSameDrawable(target.getDrawable()); - } - - private boolean hasCompoundDrawable(TextView target) { - for (Drawable drawable : target.getCompoundDrawables()) { - if (isSameDrawable(drawable)) { - return true; - } - } - return false; - } - - private boolean hasBackground(View target) { - return isSameDrawable(target.getBackground()); - } - - private boolean isSameDrawable(Drawable drawable) { - if (drawable == null) { - return false; - } - // if those are both bitmap drawables, compare their bitmaps (ignores color filters, which is what we want!) - if (mIgnoreFilters && drawable instanceof BitmapDrawable && expectedDrawable instanceof BitmapDrawable) { - return ((BitmapDrawable) drawable).getBitmap().sameAs((((BitmapDrawable) expectedDrawable).getBitmap())); - } - return expectedDrawable.getConstantState().equals(drawable.getConstantState()); - } - - @Override - public void describeTo(Description description) { - description.appendText("with drawable from resource id: "); - description.appendValue(mResourceId); - if (resourceName != null) { - description.appendText("["); - description.appendText(resourceName); - description.appendText("]"); - } - } - - public static DrawableMatcher withDrawable(int resourceId, boolean ignoreFilters) { - return new DrawableMatcher(resourceId, ignoreFilters); - } - public static DrawableMatcher withDrawable(int resourceId) { - return new DrawableMatcher(resourceId, true); - } - -} diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/EditTextMatchers.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/EditTextMatchers.java deleted file mode 100644 index a1df7912f..000000000 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/EditTextMatchers.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2015 Vincent Breitmoser - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.matcher; - -import android.content.Context; -import android.text.method.TransformationMethod; -import android.view.View; -import android.widget.EditText; - -import org.hamcrest.Description; -import org.hamcrest.TypeSafeMatcher; - -public class EditTextMatchers { - - public static TypeSafeMatcher withError(final int errorResId) { - return new TypeSafeMatcher() { - - @Override - public boolean matchesSafely(View view) { - Context context = view.getContext(); - - if (view instanceof EditText) { - CharSequence error = ((EditText) view).getError(); - return error != null && error.equals(context.getString(errorResId)); - } - - return false; - } - - @Override - public void describeTo(Description description) { - description.appendText("EditText with error"); - } - - }; - } - - public static TypeSafeMatcher withTransformationMethod(final Class transformationClass) { - return new TypeSafeMatcher() { - - @Override - public boolean matchesSafely(View view) { - if (view instanceof EditText) { - TransformationMethod transformation = ((EditText) view).getTransformationMethod(); - return transformation != null && transformationClass.isInstance(transformation); - } - - return false; - } - - @Override - public void describeTo(Description description) { - description.appendText("EditText with transformation method"); - } - - }; - } - -} diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/remote/OpenPgpServiceTest.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/remote/OpenPgpServiceTest.java deleted file mode 100644 index 064d4cd25..000000000 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/remote/OpenPgpServiceTest.java +++ /dev/null @@ -1,167 +0,0 @@ -package org.sufficientlysecure.keychain.remote; - - -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.os.IBinder; -import androidx.test.platform.app.InstrumentationRegistry; -import androidx.test.rule.ServiceTestRule; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import android.test.suitebuilder.annotation.LargeTest; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.openintents.openpgp.IOpenPgpService2; -import org.openintents.openpgp.util.OpenPgpApi; -import org.sufficientlysecure.keychain.R; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; - -import static androidx.test.espresso.Espresso.closeSoftKeyboard; -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.typeText; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertThat; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.cleanupForTests; - - -@RunWith(AndroidJUnit4.class) -@LargeTest -public class OpenPgpServiceTest { - - public static final int ACTIVITY_WAIT_TIME = 2 * 1000; - - @Rule - public final ServiceTestRule mServiceRule = new ServiceTestRule(); - - private OpenPgpApi mApi; - - @Before - public void setUp() throws Exception { - Context context = InstrumentationRegistry.getTargetContext(); - - cleanupForTests(context); - - Intent serviceIntent = new Intent(context, OpenPgpService2.class); - IBinder binder = mServiceRule.bindService(serviceIntent); - - mApi = new OpenPgpApi(context, IOpenPgpService2.Stub.asInterface(binder)); - } - - @Test - public void testStuff() throws Exception { - // TODO why does this not ask for general usage permissions?! - - { - Intent intent = new Intent(); - intent.setAction(OpenPgpApi.ACTION_ENCRYPT); - intent.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); - intent.putExtra(OpenPgpApi.EXTRA_KEY_IDS, new long[]{0x9D604D2F310716A3L}); - - ByteArrayInputStream is = new ByteArrayInputStream("swag".getBytes()); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - - Intent result = mApi.executeApi(intent, is, os); - - assertThat("result is pending accept", - result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR), - is(OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED)); - - PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); - pi.send(); - - Thread.sleep(ACTIVITY_WAIT_TIME); // Wait for activity to start - onView(withText(R.string.button_allow)).perform(click()); - } - - byte[] ciphertext; - { - Intent intent = new Intent(); - intent.setAction(OpenPgpApi.ACTION_ENCRYPT); - intent.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true); - intent.putExtra(OpenPgpApi.EXTRA_KEY_IDS, new long[]{0x9D604D2F310716A3L}); - - ByteArrayInputStream is = new ByteArrayInputStream("swag".getBytes()); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - - Intent result = mApi.executeApi(intent, is, os); - - assertThat("result is encrypt ok", - result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR), - is(OpenPgpApi.RESULT_CODE_SUCCESS)); - - ciphertext = os.toByteArray(); - } - - { // decrypt - Intent intent = new Intent(); - intent.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY); - - ByteArrayInputStream is = new ByteArrayInputStream(ciphertext); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - - Intent result = mApi.executeApi(intent, is, os); - - assertThat("result is pending input", - result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR), - is(OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED)); - - PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); - pi.send(); - - Thread.sleep(ACTIVITY_WAIT_TIME); // Wait for activity to start - onView(withText(R.string.button_allow)).perform(click()); - } - - { // decrypt again, this time pending passphrase - Intent intent = new Intent(); - intent.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY); - - ByteArrayInputStream is = new ByteArrayInputStream(ciphertext); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - - Intent result = mApi.executeApi(intent, is, os); - - assertThat("result is pending passphrase", - result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR), - is(OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED)); - - PendingIntent pi = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT); - pi.send(); - - Thread.sleep(ACTIVITY_WAIT_TIME); // Wait for activity to start - onView(withId(R.id.passphrase_passphrase)).perform(typeText("x")); - - // Needed to correctly execute test on Travis - closeSoftKeyboard(); - Thread.sleep(1 * 1000); - - onView(withText(R.string.btn_unlock)).perform(click()); - } - - { // decrypt again, NOW it should work with passphrase cached =) - Intent intent = new Intent(); - intent.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY); - - ByteArrayInputStream is = new ByteArrayInputStream(ciphertext); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - - Intent result = mApi.executeApi(intent, is, os); - - assertThat("result is decrypt ok", - result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR), - is(OpenPgpApi.RESULT_CODE_SUCCESS)); - - byte[] plaintext = os.toByteArray(); - assertThat("decrypted plaintext matches plaintext", new String(plaintext), is("swag")); - } - } - -} diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/AsymmetricFileOperationTests.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/AsymmetricFileOperationTests.java deleted file mode 100644 index 139de28e7..000000000 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/AsymmetricFileOperationTests.java +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright (C) 2015 Vincent Breitmoser - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.ui; - - -import android.annotation.TargetApi; -import android.app.Activity; -import android.app.Instrumentation.ActivityResult; -import android.content.Intent; -import android.net.Uri; -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; -import androidx.test.espresso.intent.Intents; -import androidx.test.espresso.intent.rule.IntentsTestRule; -import android.widget.AdapterView; - -import org.junit.Before; -import org.junit.Rule; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.AndroidTestHelpers; -import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.ui.util.Notify.Style; - -import java.io.File; - -import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; -import static androidx.test.espresso.Espresso.onData; -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu; -import static androidx.test.espresso.Espresso.pressBack; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.typeText; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasCategories; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtraWithKey; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasType; -import static androidx.test.espresso.matcher.ViewMatchers.assertThat; -import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; -import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom; -import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.CoreMatchers.allOf; -import static org.hamcrest.CoreMatchers.hasItem; -import static org.hamcrest.CoreMatchers.is; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.checkSnackbar; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.getImageNames; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.importKeysFromResource; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.pickRandom; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.randomString; -import static org.sufficientlysecure.keychain.actions.CustomActions.tokenEncryptViewAddToken; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.isRecyclerItemView; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withDisplayedChild; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withEncryptionStatus; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withKeyItemId; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withSignatureMyKey; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withSignatureNone; - -//TODO This test is disabled because it needs to be fixed to work with updated code -//@RunWith(AndroidJUnit4.class) -//@LargeTest -public class AsymmetricFileOperationTests { - - @Rule - public final IntentsTestRule mActivity - = new IntentsTestRule(MainActivity.class) { - @Override - protected Intent getActivityIntent() { - Intent intent = super.getActivityIntent(); - intent.putExtra(MainActivity.EXTRA_SKIP_FIRST_TIME, true); - intent.putExtra(MainActivity.EXTRA_INIT_FRAG, MainActivity.ID_ENCRYPT_DECRYPT); - return intent; - } - }; - - @Before - public void setUp() throws Exception { - Activity activity = mActivity.getActivity(); - - AndroidTestHelpers.copyFiles(); - - // import these two, make sure they're there - importKeysFromResource(activity, "x.sec.asc"); - - // make sure no passphrases are cached - PassphraseCacheService.clearCachedPassphrases(activity); - } - - //@Test - public void testFileSaveEncryptDecrypt() throws Exception { - - // navigate to 'encrypt text' - onView(withId(R.id.encrypt_files)).perform(click()); - - File file = pickRandom(getImageNames()); - File outputFile = new File(getInstrumentation().getTargetContext().getFilesDir(), "output-token.gpg"); - - { // encrypt - - // the EncryptKeyCompletionView is tested individually - onView(withId(R.id.recipient_list)).perform(tokenEncryptViewAddToken(0x9D604D2F310716A3L)); - - handleAddFileIntent(file); - onView(withId(R.id.file_list_entry_add)).perform(click()); - - handleSaveEncryptedFileIntent(outputFile); - onView(withId(R.id.encrypt_save)).perform(click()); - - assertThat("output file has been written", true, is(outputFile.exists())); - - } - - // go to decrypt from clipboard view - pressBack(); - - handleOpenFileIntentKitKat(outputFile); - onView(withId(R.id.decrypt_files)).perform(click()); - - { // decrypt - onView(withId(R.id.passphrase_passphrase)).perform(typeText("x")); - onView(withText(R.string.btn_unlock)).perform(click()); - - onView(isRecyclerItemView(R.id.decrypted_files_list, - hasDescendant(withText(file.getName())))) - .check(matches(allOf(withEncryptionStatus(true), withSignatureNone()))); - } - - { // delete original file - - // open context menu - onView(allOf(isDescendantOfA(isRecyclerItemView(R.id.decrypted_files_list, - hasDescendant(withText(file.getName())))), - withId(R.id.context_menu))).perform(click()); - - // delete file - onView(withText(R.string.btn_delete_original)).perform(click()); - - checkSnackbar(Style.OK, R.string.file_delete_ok); - assertThat("output file has been deleted", false, is(outputFile.exists())); - - // open context menu - onView(allOf(isDescendantOfA(isRecyclerItemView(R.id.decrypted_files_list, - hasDescendant(withText(file.getName())))), - withId(R.id.context_menu))).perform(click()); - - // delete file - onView(withText(R.string.btn_delete_original)).perform(click()); - - checkSnackbar(Style.WARN, R.string.file_delete_none); - - } - - { // save file (*after* deletion~) - - // open context menu - onView(allOf(isDescendantOfA(isRecyclerItemView(R.id.decrypted_files_list, - hasDescendant(withText(file.getName())))), - withId(R.id.context_menu))).perform(click()); - - File savedFile = - new File(getInstrumentation().getTargetContext().getFilesDir(), "vo.png"); - handleSaveDecryptedFileIntent(savedFile, file.getName()); - - // save decrypted content - onView(withText(R.string.btn_save_file)).perform(click()); - - checkSnackbar(Style.OK, R.string.file_saved); - assertThat("decrypted file has been saved", true, is(savedFile.exists())); - - // cleanup - // noinspection ResultOfMethodCallIgnored - file.delete(); - - } - - } - - private void handleAddFileIntent(File file) { - if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) { - handleAddFileIntentKitKat(file); - } else { - handleAddFileIntentOlder(file); - } - } - - @TargetApi(VERSION_CODES.KITKAT) - private void handleAddFileIntentKitKat(File file) { - Intent data = new Intent(); - data.setData(Uri.fromFile(file)); - - Intents.intending(allOf( - hasAction(Intent.ACTION_OPEN_DOCUMENT), - hasType("*/*"), - hasCategories(hasItem(Intent.CATEGORY_OPENABLE)), - hasExtraWithKey(Intent.EXTRA_ALLOW_MULTIPLE) - )).respondWith( - new ActivityResult(Activity.RESULT_OK, data) - ); - } - - private void handleAddFileIntentOlder(File file) { - Intent data = new Intent(); - data.setData(Uri.fromFile(file)); - - Intents.intending(allOf( - hasAction(Intent.ACTION_GET_CONTENT), - hasType("*/*"), - hasCategories(hasItem(Intent.CATEGORY_OPENABLE)) - )).respondWith( - new ActivityResult(Activity.RESULT_OK, data) - ); - } - - @TargetApi(VERSION_CODES.KITKAT) - private void handleSaveDecryptedFileIntent(File file, String expectedTitle) { - Intent data = new Intent(); - data.setData(Uri.fromFile(file)); - - Intents.intending(allOf( - hasAction(Intent.ACTION_CREATE_DOCUMENT), - hasExtra("android.content.extra.SHOW_ADVANCED", true), - hasExtra(Intent.EXTRA_TITLE, expectedTitle), - hasCategories(hasItem(Intent.CATEGORY_OPENABLE)) - )).respondWith( - new ActivityResult(Activity.RESULT_OK, data) - ); - } - - @TargetApi(VERSION_CODES.KITKAT) - private void handleSaveEncryptedFileIntent(File file) { - - try { - //noinspection ResultOfMethodCallIgnored - file.delete(); - } catch (Exception e) { - // nvm - } - - Intent data = new Intent(); - data.setData(Uri.fromFile(file)); - - Intents.intending(allOf( - hasAction(Intent.ACTION_CREATE_DOCUMENT), - hasType("*/*"), - hasExtra("android.content.extra.SHOW_ADVANCED", true), - hasCategories(hasItem(Intent.CATEGORY_OPENABLE)) - )).respondWith( - new ActivityResult(Activity.RESULT_OK, data) - ); - } - - @TargetApi(VERSION_CODES.KITKAT) - private void handleOpenFileIntentKitKat(File file) { - Intent data = new Intent(); - data.setData(Uri.fromFile(file)); - - Intents.intending(allOf( - hasAction(Intent.ACTION_OPEN_DOCUMENT), - hasType("*/*"), - hasCategories(hasItem(Intent.CATEGORY_OPENABLE)) - // hasExtraWithKey(Intent.EXTRA_ALLOW_MULTIPLE) - )).respondWith( - new ActivityResult(Activity.RESULT_OK, data) - ); - } - - //@Test - public void testSignVerify() throws Exception { - - String cleartext = randomString(10, 30); - - // navigate to 'encrypt text' - onView(withId(R.id.encrypt_text)).perform(click()); - - { // sign - - onView(withId(R.id.encrypt_copy)).perform(click()); - checkSnackbar(Style.ERROR, R.string.error_empty_text); - - onView(withId(R.id.result_signature_icon)).check(matches(withDisplayedChild(0))); - onView(withId(R.id.sign)).perform(click()); - onData(withKeyItemId(0x9D604D2F310716A3L)) - .inAdapterView(isAssignableFrom(AdapterView.class)) - .perform(click()); - onView(withId(R.id.result_signature_icon)).check(matches(withDisplayedChild(1))); - - onView(withId(R.id.encrypt_text_text)).perform(typeText(cleartext)); - - onView(withId(R.id.encrypt_copy)).perform(click()); - - onView(withId(R.id.passphrase_passphrase)).perform(typeText("x")); - onView(withText(R.string.btn_unlock)).perform(click()); - - checkSnackbar(Style.OK, R.string.msg_se_success); - - } - - // go to decrypt from clipboard view - pressBack(); - - onView(withId(R.id.decrypt_from_clipboard)).perform(click()); - - { // decrypt - - onView(isRecyclerItemView(R.id.decrypted_files_list, - hasDescendant(withText(R.string.filename_unknown)))) - .check(matches(allOf(withEncryptionStatus(false), withSignatureMyKey()))); - - // open context menu - onView(allOf(isDescendantOfA(isRecyclerItemView(R.id.decrypted_files_list, - hasDescendant(withText(R.string.filename_unknown)))), - withId(R.id.context_menu))).perform(click()); - - // check if log looks ok - onView(withText(R.string.snackbar_details)).perform(click()); - onView(withText(R.string.msg_dc_clear_signature_ok)).check(matches(isDisplayed())); - pressBack(); - - } - - } - - //@Test - public void testGeneralErrorHandling() throws Exception { - - // navigate to encrypt files fragment - onView(withId(R.id.encrypt_files)).perform(click()); - - File[] files = getImageNames(); - - { // encrypt screen - - onView(withId(R.id.encrypt_share)).perform(click()); - checkSnackbar(Style.ERROR, R.string.error_no_file_selected); - - handleAddFileIntent(files[0]); - onView(withId(R.id.file_list_entry_add)).perform(click()); - - handleAddFileIntent(files[1]); - onView(withId(R.id.file_list_entry_add)).perform(click()); - - onView(withId(R.id.encrypt_share)).perform(click()); - checkSnackbar(Style.ERROR, R.string.select_encryption_key); - - onView(withId(R.id.sign)).perform(click()); - onData(withKeyItemId(0x9D604D2F310716A3L)) - .inAdapterView(isAssignableFrom(AdapterView.class)) - .perform(click()); - - onView(withId(R.id.encrypt_share)).perform(click()); - checkSnackbar(Style.ERROR, R.string.error_detached_signature); - - // the EncryptKeyCompletionView is tested individually - onView(withId(R.id.recipient_list)).perform(tokenEncryptViewAddToken(0x9D604D2F310716A3L)); - - onView(withId(R.id.encrypt_save)).perform(click()); - checkSnackbar(Style.ERROR, R.string.error_multi_files); - - openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext()); - onView(withText(R.string.btn_copy_encrypted_signed)).perform(click()); - checkSnackbar(Style.ERROR, R.string.error_multi_clipboard); - - } - - } - -} diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/AsymmetricTextOperationTests.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/AsymmetricTextOperationTests.java deleted file mode 100644 index b2bda9180..000000000 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/AsymmetricTextOperationTests.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2015 Vincent Breitmoser - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.ui; - - -import android.app.Activity; -import android.content.Intent; -import androidx.test.rule.ActivityTestRule; -import android.widget.AdapterView; - -import org.junit.Before; -import org.junit.Rule; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.ui.util.Notify.Style; -import org.sufficientlysecure.keychain.util.FileHelper; - -import static androidx.test.espresso.Espresso.onData; -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.Espresso.pressBack; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.typeText; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; -import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom; -import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.CoreMatchers.allOf; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.checkSnackbar; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.importKeysFromResource; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.randomString; -import static org.sufficientlysecure.keychain.actions.CustomActions.tokenEncryptViewAddToken; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.isRecyclerItemView; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withDisplayedChild; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withEncryptionStatus; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withKeyItemId; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withSignatureMyKey; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withSignatureNone; - -//TODO This test is disabled because it needs to be fixed to work with updated code -//@RunWith(AndroidJUnit4.class) -//@LargeTest -public class AsymmetricTextOperationTests { - - @Rule - public final ActivityTestRule mActivity - = new ActivityTestRule(MainActivity.class) { - @Override - protected Intent getActivityIntent() { - Intent intent = super.getActivityIntent(); - intent.putExtra(MainActivity.EXTRA_SKIP_FIRST_TIME, true); - intent.putExtra(MainActivity.EXTRA_INIT_FRAG, MainActivity.ID_ENCRYPT_DECRYPT); - return intent; - } - }; - - @Before - public void setUp() throws Exception { - Activity activity = mActivity.getActivity(); - - // import these two, make sure they're there - importKeysFromResource(activity, "x.sec.asc"); - - // make sure no passphrases are cached - PassphraseCacheService.clearCachedPassphrases(activity); - } - - //@Test - public void testTextEncryptDecryptFromToken() throws Exception { - - // navigate to 'encrypt text' - onView(withId(R.id.encrypt_text)).perform(click()); - - String cleartext = randomString(10, 30); - - { // encrypt - - // the EncryptKeyCompletionView is tested individually - onView(withId(R.id.result_encryption_icon)).check(matches(withDisplayedChild(0))); - onView(withId(R.id.recipient_list)).perform(tokenEncryptViewAddToken(0x9D604D2F310716A3L)); - onView(withId(R.id.result_encryption_icon)).check(matches(withDisplayedChild(1))); - - onView(withId(R.id.encrypt_text_text)).perform(typeText(cleartext)); - - onView(withId(R.id.encrypt_copy)).perform(click()); - } - - // go to decrypt from clipboard view - pressBack(); - onView(withId(R.id.decrypt_from_clipboard)).perform(click()); - - { // decrypt - onView(withId(R.id.passphrase_passphrase)).perform(typeText("x")); - onView(withText(R.string.btn_unlock)).perform(click()); - - onView(isRecyclerItemView(R.id.decrypted_files_list, - hasDescendant(withText(R.string.filename_unknown_text)))) - .check(matches(allOf( - hasDescendant(withText(FileHelper.readableFileSize(cleartext.length()))), - withEncryptionStatus(true), - withSignatureNone() - ))); - - } - - } - - //@Test - public void testSignVerify() throws Exception { - - String cleartext = randomString(10, 30); - - // navigate to 'encrypt text' - onView(withId(R.id.encrypt_text)).perform(click()); - - { // sign - - onView(withId(R.id.encrypt_copy)).perform(click()); - checkSnackbar(Style.ERROR, R.string.error_empty_text); - - onView(withId(R.id.result_signature_icon)).check(matches(withDisplayedChild(0))); - onView(withId(R.id.sign)).perform(click()); - onData(withKeyItemId(0x9D604D2F310716A3L)) - .inAdapterView(isAssignableFrom(AdapterView.class)) - .perform(click()); - onView(withId(R.id.result_signature_icon)).check(matches(withDisplayedChild(1))); - - onView(withId(R.id.encrypt_text_text)).perform(typeText(cleartext)); - - onView(withId(R.id.encrypt_copy)).perform(click()); - - onView(withId(R.id.passphrase_passphrase)).perform(typeText("x")); - onView(withText(R.string.btn_unlock)).perform(click()); - - checkSnackbar(Style.OK, R.string.msg_se_success); - - } - - // go to decrypt from clipboard view - pressBack(); - - onView(withId(R.id.decrypt_from_clipboard)).perform(click()); - - { // decrypt - - onView(isRecyclerItemView(R.id.decrypted_files_list, - hasDescendant(withText(R.string.filename_unknown)))) - .check(matches(allOf(withEncryptionStatus(false), withSignatureMyKey()))); - - // open context menu - onView(allOf(isDescendantOfA(isRecyclerItemView(R.id.decrypted_files_list, - hasDescendant(withText(R.string.filename_unknown)))), - withId(R.id.context_menu))).perform(click()); - - // check if log looks ok - onView(withText(R.string.snackbar_details)).perform(click()); - onView(withText(R.string.msg_dc_clear_signature_ok)).check(matches(isDisplayed())); - pressBack(); - - } - - } - -} diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/CreateKeyActivityTest.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/CreateKeyActivityTest.java deleted file mode 100644 index f9a53f4b4..000000000 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/CreateKeyActivityTest.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright (C) 2015 Dominik Schürmann - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.ui; - - -import androidx.test.espresso.matcher.ViewMatchers; -import androidx.test.rule.ActivityTestRule; - -import android.test.suitebuilder.annotation.LargeTest; - -import org.junit.Rule; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.swipeLeft; -import static androidx.test.espresso.action.ViewActions.typeText; -import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.RootMatchers.isDialog; -import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; -import static androidx.test.espresso.matcher.ViewMatchers.hasSibling; -import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.Matchers.allOf; - - -//TODO This test is disabled because it needs to be fixed to work with updated code -//@RunWith(AndroidJUnit4.class) -//@LargeTest -public class CreateKeyActivityTest { - - public static final String SAMPLE_NAME = "Sample Name"; - public static final String SAMPLE_EMAIL = "sample_email@gmail.com"; - public static final String SAMPLE_ADDITIONAL_EMAIL = "sample_additional_email@gmail.com"; - public static final String SAMPLE_PASSWORD = "sample_password"; - - @Rule - public final ActivityTestRule mActivity - = new ActivityTestRule<>(CreateKeyActivity.class); - - //@Test - public void testCreateMyKey() { - /* - - mActivity.getActivity(); - - // Clicks create my key - onView(ViewMatchers.withId(R.id.create_key_create_key_button)) - .perform(click()); - - // Clicks next with empty name - onView(withId(R.id.create_key_next_button)) - .perform(click()); - onView(withId(R.id.create_key_name)) - .check(matches(withError(R.string.create_key_empty))); - - // Types name and clicks next - onView(withId(R.id.create_key_name)) - .perform(typeText(SAMPLE_NAME)); - onView(withId(R.id.create_key_next_button)) - .perform(click()); - - // Clicks next with empty email - onView(withId(R.id.create_key_next_button)) - .perform(click()); - onView(withId(R.id.create_key_email)) - .check(matches(withError(R.string.create_key_empty))); - - // Types email - onView(withId(R.id.create_key_email)) - .perform(typeText(SAMPLE_EMAIL)); - - // Adds same email as additional email and dismisses the snackbar - onView(withId(R.id.create_key_add_email)) - .perform(click()); - onView(withId(R.id.add_email_address)) - .perform(typeText(SAMPLE_EMAIL)); - onView(withText(android.R.string.ok)) - .inRoot(isDialog()) - .perform(click()); - onView(allOf(withId(R.id.sb__text), withText(R.string.create_key_email_already_exists_text))) - .check(matches(isDisplayed())); - onView(allOf(withId(R.id.sb__text), withText(R.string.create_key_email_already_exists_text))) - .perform(swipeLeft()); - - // Adds additional email - onView(withId(R.id.create_key_add_email)) - .perform(click()); - onView(withId(R.id.add_email_address)) - .perform(typeText(SAMPLE_ADDITIONAL_EMAIL)); - onView(withText(android.R.string.ok)) - .inRoot(isDialog()) - .perform(click()); - onView(withId(R.id.create_key_emails)) - .check(matches(hasDescendant(allOf(withId(R.id.create_key_email_item_email), withText(SAMPLE_ADDITIONAL_EMAIL))))); - - // Removes additional email and clicks next - onView(allOf(withId(R.id.create_key_email_item_delete_button), hasSibling(allOf(withId(R.id.create_key_email_item_email), withText(SAMPLE_ADDITIONAL_EMAIL))))) - .perform(click()) - .check(doesNotExist()); - onView(withId(R.id.create_key_next_button)) - .perform(click(click())); - - // Clicks next with empty password - onView(withId(R.id.create_key_next_button)) - .perform(click()); - onView(withId(R.id.create_key_passphrase)) - .check(matches(withError(R.string.create_key_empty))); - - // Types password - onView(withId(R.id.create_key_passphrase)) - .perform(typeText(SAMPLE_PASSWORD)); - - // Clicks next with empty confirm password - onView(withId(R.id.create_key_next_button)) - .perform(click()); - onView(withId(R.id.create_key_passphrase_again)) - .check(matches(withError(R.string.create_key_passphrases_not_equal))); - - // Types confirm password - onView(withId(R.id.create_key_passphrase_again)) - .perform(typeText(SAMPLE_PASSWORD)); - - // Clicks show password twice and clicks next - onView(withId(R.id.create_key_show_passphrase)) - .perform(click()); - onView(withId(R.id.create_key_passphrase)) - .check(matches(withTransformationMethod(HideReturnsTransformationMethod.class))); - onView(withId(R.id.create_key_passphrase_again)) - .check(matches(withTransformationMethod(HideReturnsTransformationMethod.class))); - onView(withId(R.id.create_key_show_passphrase)) - .perform(click()); - onView(withId(R.id.create_key_passphrase)) - .check(matches(withTransformationMethod(PasswordTransformationMethod.class))); - onView(withId(R.id.create_key_passphrase_again)) - .check(matches(withTransformationMethod(PasswordTransformationMethod.class))); - onView(withId(R.id.create_key_next_button)) - .perform(click()); - - // Verifies name and email - onView(withId(R.id.name)) - .check(matches(withText(SAMPLE_NAME))); - onView(withId(R.id.email)) - .check(matches(withText(SAMPLE_EMAIL))); - - // Verifies backstack - onView(withId(R.id.create_key_back_button)) - .perform(click()); - onView(withId(R.id.create_key_back_button)) - .perform(click()); - onView(withId(R.id.create_key_back_button)) - .perform(click()); - - onView(withId(R.id.create_key_name)) - .check(matches(withText(SAMPLE_NAME))); - onView(withId(R.id.create_key_next_button)) - .perform(click()); - - onView(withId(R.id.create_key_email)) - .check(matches(withText(SAMPLE_EMAIL))); - onView(withId(R.id.create_key_next_button)) - .perform(click()); - - // TODO: Uncomment when fixed in main -// onView(withId(R.id.create_key_passphrase)) -// .check(matches(withText(SAMPLE_PASSWORD))); -// onView(withId(R.id.create_key_passphrase_again)) -// .check(matches(withText(SAMPLE_PASSWORD))); - onView(withId(R.id.create_key_next_button)) - .perform(click()); - - onView(withId(R.id.name)) - .check(matches(withText(SAMPLE_NAME))); - onView(withId(R.id.email)) - .check(matches(withText(SAMPLE_EMAIL))); - - // Clicks create key - onView(withId(R.id.create_key_next_button)) - .perform(click()); - */ - } - -} diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/EditKeyTest.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/EditKeyTest.java deleted file mode 100644 index eebdb3af9..000000000 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/EditKeyTest.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2015 Vincent Breitmoser - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.ui; - - -import android.app.Activity; -import android.content.Intent; -import androidx.test.rule.ActivityTestRule; -import androidx.recyclerview.widget.RecyclerView; - -import org.junit.FixMethodOrder; -import org.junit.Rule; -import org.junit.runners.MethodSorters; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.util.Notify.Style; - -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnHolderItem; -import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.CoreMatchers.allOf; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.checkSnackbar; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.importKeysFromResource; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withKeyHolderId; - - -//TODO This test is disabled because it needs to be fixed to work with updated code -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -//@RunWith(AndroidJUnit4.class) -//@LargeTest -public class EditKeyTest { - - @Rule - public final ActivityTestRule mActivity - = new ActivityTestRule(MainActivity.class) { - @Override - protected Intent getActivityIntent() { - Intent intent = super.getActivityIntent(); - intent.putExtra(MainActivity.EXTRA_SKIP_FIRST_TIME, true); - return intent; - } - }; - - //@Test - public void test01Edit() throws Exception { - Activity activity = mActivity.getActivity(); - - // KeychainDatabase.getInstance(activity).clearDatabase(); - - // import key for testing, get a stable initial state - importKeysFromResource(activity, "x.sec.asc"); - - // navigate to edit key dialog - onView(allOf( - isAssignableFrom(RecyclerView.class), - withId(android.R.id.list))) - .perform(actionOnHolderItem( - withKeyHolderId(0x9D604D2F310716A3L), click())); - - onView(withId(R.id.view_key_card_user_ids_edit)).perform(click()); - - // no-op should yield snackbar - onView(withText(R.string.btn_save)).perform(click()); - checkSnackbar(Style.ERROR, R.string.msg_mf_error_noop); - - } - - -} diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/MiscCryptOperationTests.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/MiscCryptOperationTests.java deleted file mode 100644 index c399ff37e..000000000 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/MiscCryptOperationTests.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (C) 2015 Vincent Breitmoser - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.ui; - - -import android.annotation.TargetApi; -import android.app.Activity; -import android.app.Instrumentation.ActivityResult; -import android.content.ClipData; -import android.content.ClipboardManager; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Build.VERSION_CODES; -import androidx.test.espresso.intent.Intents; -import androidx.test.espresso.intent.rule.IntentsTestRule; -import androidx.recyclerview.widget.RecyclerView; - -import org.junit.Before; -import org.junit.Rule; -import org.sufficientlysecure.keychain.Constants; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.AndroidTestHelpers; -import org.sufficientlysecure.keychain.service.PassphraseCacheService; -import org.sufficientlysecure.keychain.ui.util.Notify.Style; -import org.sufficientlysecure.keychain.util.Preferences; - -import java.io.File; - -import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu; -import static androidx.test.espresso.Espresso.pressBack; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.contrib.RecyclerViewActions.actionOnHolderItem; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasCategories; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasType; -import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; -import static androidx.test.espresso.matcher.ViewMatchers.hasSibling; -import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom; -import static androidx.test.espresso.matcher.ViewMatchers.isChecked; -import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA; -import static androidx.test.espresso.matcher.ViewMatchers.isNotChecked; -import static androidx.test.espresso.matcher.ViewMatchers.withChild; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.CoreMatchers.allOf; -import static org.hamcrest.CoreMatchers.hasItem; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.checkSnackbar; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.dismissSnackbar; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.getImageNames; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.importKeysFromResource; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.pickRandom; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.randomString; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.isRecyclerItemView; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withDisplayedChild; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withKeyHolderId; -import static org.sufficientlysecure.keychain.matcher.DrawableMatcher.withDrawable; - -//TODO This test is disabled because it needs to be fixed to work with updated code -//@RunWith(AndroidJUnit4.class) -//@LargeTest -public class MiscCryptOperationTests { - - @Rule - public final IntentsTestRule mActivityRule - = new IntentsTestRule(MainActivity.class) { - @Override - protected Intent getActivityIntent() { - Intent intent = super.getActivityIntent(); - intent.putExtra(MainActivity.EXTRA_SKIP_FIRST_TIME, true); - intent.putExtra(MainActivity.EXTRA_INIT_FRAG, MainActivity.ID_ENCRYPT_DECRYPT); - return intent; - } - }; - private Activity mActivity; - - @Before - public void setUp() throws Exception { - // clear dis shit - Preferences.getPreferences(getInstrumentation().getTargetContext()).clear(); - - mActivity = mActivityRule.getActivity(); - - AndroidTestHelpers.copyFiles(); - - // import these two, make sure they're there - importKeysFromResource(mActivity, "x.sec.asc"); - - // make sure no passphrases are cached - PassphraseCacheService.clearCachedPassphrases(mActivity); - } - - //@Test - public void testDecryptNonPgpFile() throws Exception { - - // decrypt any non-pgp file - File file = pickRandom(getImageNames()); - handleOpenFileIntentKitKat(file); - onView(withId(R.id.decrypt_files)).perform(click()); - - { // decrypt - - // open context menu - onView(allOf(isDescendantOfA(isRecyclerItemView(R.id.decrypted_files_list, - hasDescendant(allOf( - hasDescendant(withDrawable(R.drawable.status_signature_invalid_cutout_24dp, true)), - hasDescendant(withText(R.string.msg_dc_error_invalid_data)))))), - withId(R.id.result_error_log))).perform(click()); - - } - - } - - //@Test - public void testDecryptEmptySelection() throws Exception { - - // decrypt any non-pgp file - handleOpenFileEmptyKitKat(); - onView(withId(R.id.decrypt_files)).perform(click()); - - checkSnackbar(Style.ERROR, R.string.no_file_selected); - - } - - //@Test - public void testDecryptEmptyClipboard() throws Exception { - - // decrypt any non-pgp file - ClipboardManager clipboard = (ClipboardManager) mActivity.getSystemService(Context.CLIPBOARD_SERVICE); - clipboard.setPrimaryClip(ClipData.newPlainText("", "")); - - onView(withId(R.id.decrypt_from_clipboard)).perform(click()); - checkSnackbar(Style.ERROR, R.string.error_clipboard_empty); - - } - - //@Test - public void testDecryptNonPgpClipboard() throws Exception { - - // decrypt any non-pgp file - ClipboardManager clipboard = (ClipboardManager) mActivity.getSystemService(Context.CLIPBOARD_SERVICE); - ClipData clip = ClipData.newPlainText(Constants.CLIPBOARD_LABEL, randomString(0, 50)); - clipboard.setPrimaryClip(clip); - onView(withId(R.id.decrypt_from_clipboard)).perform(click()); - - { // decrypt - - // open context menu - onView(allOf(isDescendantOfA(isRecyclerItemView(R.id.decrypted_files_list, - hasDescendant(allOf( - hasDescendant(withDrawable(R.drawable.status_signature_invalid_cutout_24dp, true)), - hasDescendant(withText(R.string.msg_dc_error_invalid_data)))))), - withId(R.id.result_error_log))).perform(click()); - - } - - } - - @TargetApi(VERSION_CODES.KITKAT) - private void handleOpenFileEmptyKitKat() { - Intent data = new Intent(); - data.setData(null); - - Intents.intending(allOf( - hasAction(Intent.ACTION_OPEN_DOCUMENT), - hasType("*/*"), - hasCategories(hasItem(Intent.CATEGORY_OPENABLE)) - // hasExtraWithKey(Intent.EXTRA_ALLOW_MULTIPLE) - )).respondWith( - new ActivityResult(Activity.RESULT_OK, data) - ); - } - - @TargetApi(VERSION_CODES.KITKAT) - private void handleOpenFileIntentKitKat(File file) { - Intent data = new Intent(); - data.setData(Uri.fromFile(file)); - - Intents.intending(allOf( - hasAction(Intent.ACTION_OPEN_DOCUMENT), - hasType("*/*"), - hasCategories(hasItem(Intent.CATEGORY_OPENABLE)) - // hasExtraWithKey(Intent.EXTRA_ALLOW_MULTIPLE) - )).respondWith( - new ActivityResult(Activity.RESULT_OK, data) - ); - } - - //@Test - public void testEncryptTokenFromKeyView() throws Exception { - onView(allOf( - isAssignableFrom(RecyclerView.class), - withId(android.R.id.list))) - .perform(actionOnHolderItem( - withKeyHolderId(0x9D604D2F310716A3L), click())); - - onView(withId(R.id.view_key_action_encrypt_text)).perform(click()); - - // make sure the encrypt is correctly set - onView(withId(R.id.result_encryption_icon)).check(matches(withDisplayedChild(1))); - // TODO check token id - - } - - //@Test - public void testMenuSaveDefault() throws Exception { - - onView(withId(R.id.encrypt_files)).perform(click()); - - { // save checked options - - openActionBarOverflowOrOptionsMenu(mActivity); - - // check initial button states - onView(allOf(withId(R.id.checkbox), - hasSibling(withChild(withText(R.string.label_delete_after_encryption))))) - .check(matches(isNotChecked())); - onView(allOf(withId(R.id.checkbox), hasSibling(withChild(withText(R.string.label_enable_compression))))) - .check(matches(isChecked())); - onView(allOf(withId(R.id.checkbox), hasSibling(withChild(withText(R.string.label_encrypt_filenames))))) - .check(matches(isChecked())); - onView(allOf(withId(R.id.checkbox), hasSibling(withChild(withText(R.string.label_file_ascii_armor))))) - .check(matches(isNotChecked())); - - // press some buttons - - onView(withText(R.string.label_enable_compression)).perform(click()); - checkSnackbar(Style.OK, R.string.snack_compression_off); - onView(withText(R.string.btn_save_default)).perform(click()); - checkSnackbar(Style.OK, R.string.btn_saved); - dismissSnackbar(); - - openActionBarOverflowOrOptionsMenu(mActivity); - onView(withText(R.string.label_encrypt_filenames)).perform(click()); - checkSnackbar(Style.OK, R.string.snack_encrypt_filenames_off); - onView(withText(R.string.btn_save_default)).perform(click()); - checkSnackbar(Style.OK, R.string.btn_saved); - dismissSnackbar(); - - openActionBarOverflowOrOptionsMenu(mActivity); - onView(withText(R.string.label_file_ascii_armor)).perform(click()); - checkSnackbar(Style.OK, R.string.snack_armor_on); - onView(withText(R.string.btn_save_default)).perform(click()); - checkSnackbar(Style.OK, R.string.btn_saved); - dismissSnackbar(); - - } - - pressBack(); - onView(withId(R.id.encrypt_files)).perform(click()); - - { // save checked options - - openActionBarOverflowOrOptionsMenu(mActivity); - - // check initial button states (as saved from before!) - onView(allOf(withId(R.id.checkbox), - hasSibling(withChild(withText(R.string.label_delete_after_encryption))))) - .check(matches(isNotChecked())); - onView(allOf(withId(R.id.checkbox), hasSibling(withChild(withText(R.string.label_enable_compression))))) - .check(matches(isNotChecked())); - onView(allOf(withId(R.id.checkbox), hasSibling(withChild(withText(R.string.label_encrypt_filenames))))) - .check(matches(isNotChecked())); - onView(allOf(withId(R.id.checkbox), hasSibling(withChild(withText(R.string.label_file_ascii_armor))))) - .check(matches(isChecked())); - - } - - } - -} diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/SymmetricTextOperationTests.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/SymmetricTextOperationTests.java deleted file mode 100644 index 15155e446..000000000 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/SymmetricTextOperationTests.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2015 Vincent Breitmoser - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.ui; - - -import android.app.Activity; -import android.app.Instrumentation.ActivityResult; -import android.content.Intent; -import androidx.test.espresso.intent.rule.IntentsTestRule; - -import org.junit.FixMethodOrder; -import org.junit.Rule; -import org.junit.runners.MethodSorters; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.provider.TemporaryFileProvider; -import org.sufficientlysecure.keychain.ui.util.Notify.Style; - -import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu; -import static androidx.test.espresso.Espresso.pressBack; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.typeText; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.intent.Intents.intending; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasData; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtraWithKey; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasFlags; -import static androidx.test.espresso.intent.matcher.IntentMatchers.hasType; -import static androidx.test.espresso.intent.matcher.UriMatchers.hasHost; -import static androidx.test.espresso.intent.matcher.UriMatchers.hasScheme; -import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; -import static androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static androidx.test.espresso.matcher.ViewMatchers.withText; -import static org.hamcrest.CoreMatchers.allOf; -import static org.hamcrest.Matchers.equalTo; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.checkSnackbar; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.randomString; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.isRecyclerItemView; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withEncryptionStatus; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withSignatureNone; - -//TODO This test is disabled because it needs to be fixed to work with updated code -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -//@RunWith(AndroidJUnit4.class) -//@LargeTest -public class SymmetricTextOperationTests { - - public static final String PASSPHRASE = randomString(5, 20); - - @Rule - public final IntentsTestRule mActivity - = new IntentsTestRule(MainActivity.class) { - @Override - protected Intent getActivityIntent() { - Intent intent = super.getActivityIntent(); - intent.putExtra(MainActivity.EXTRA_SKIP_FIRST_TIME, true); - intent.putExtra(MainActivity.EXTRA_INIT_FRAG, MainActivity.ID_ENCRYPT_DECRYPT); - return intent; - } - }; - - //@Test - public void testSymmetricCryptClipboard() throws Exception { - - mActivity.getActivity(); - - String text = randomString(10, 30); - - // navigate to encrypt/decrypt - onView(withId(R.id.encrypt_text)).perform(click()); - - { - onView(withId(R.id.encrypt_text_text)).perform(typeText(text)); - - openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext()); - onView(withText(R.string.label_symmetric)).perform(click()); - - onView(withId(R.id.passphrase)).perform(typeText(PASSPHRASE)); - - onView(withId(R.id.encrypt_copy)).perform(click()); - - checkSnackbar(Style.ERROR, R.string.passphrases_do_not_match); - - onView(withId(R.id.passphraseAgain)).perform(typeText(PASSPHRASE)); - - onView(withId(R.id.encrypt_text_text)).check(matches(withText(text))); - - onView(withId(R.id.encrypt_copy)).perform(click()); - - checkSnackbar(Style.OK, R.string.msg_se_success); - } - - // go to decrypt from clipboard view - pressBack(); - onView(withId(R.id.decrypt_from_clipboard)).perform(click()); - - { - onView(withId(R.id.passphrase_passphrase)).perform(typeText(PASSPHRASE)); - onView(withText(R.string.btn_unlock)).perform(click()); - - onView(isRecyclerItemView(R.id.decrypted_files_list, - hasDescendant(withText(R.string.filename_unknown_text)))) - .check(matches(allOf(withEncryptionStatus(true), withSignatureNone()))); - - intending(allOf( - hasAction("android.intent.action.CHOOSER"), - hasExtra(equalTo(Intent.EXTRA_INTENT), allOf( - hasAction(Intent.ACTION_VIEW), - hasFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION), - hasData(allOf(hasScheme("content"), hasHost(TemporaryFileProvider.AUTHORITY))), - hasType("text/plain") - )) - )).respondWith(new ActivityResult(Activity.RESULT_OK, null)); - - onView(allOf(isDescendantOfA(isRecyclerItemView(R.id.decrypted_files_list, - hasDescendant(withText(R.string.filename_unknown_text)))), - withId(R.id.file))).perform(click()); - - } - - } - - //@Test - public void testSymmetricCryptShare() throws Exception { - - mActivity.getActivity(); - - String text = randomString(10, 30); - - // navigate to encrypt/decrypt - onView(withId(R.id.encrypt_text)).perform(click()); - - { - onView(withId(R.id.encrypt_text_text)).perform(typeText(text)); - - openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext()); - onView(withText(R.string.label_symmetric)).perform(click()); - - onView(withId(R.id.passphrase)).perform(typeText(PASSPHRASE)); - - onView(withId(R.id.passphraseAgain)).perform(typeText(PASSPHRASE)); - - onView(withId(R.id.encrypt_text_text)).check(matches(withText(text))); - - intending(allOf( - hasAction("android.intent.action.CHOOSER"), - hasExtra(equalTo(Intent.EXTRA_INTENT), allOf( - hasAction(Intent.ACTION_SEND), - hasFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION), - hasExtraWithKey(Intent.EXTRA_TEXT), - hasType("text/plain") - )) - )).respondWith(new ActivityResult(Activity.RESULT_OK, null)); - - onView(withId(R.id.encrypt_share)).perform(click()); - - } - - } - - -} diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionViewTest.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionViewTest.java deleted file mode 100644 index 8cb9e2bdd..000000000 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionViewTest.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2015 Vincent Breitmoser - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.ui.widget; - - -import android.app.Activity; -import android.content.Intent; -import androidx.test.espresso.action.ViewActions; -import androidx.test.espresso.matcher.RootMatchers; -import androidx.test.espresso.matcher.ViewMatchers; -import androidx.test.rule.ActivityTestRule; -import android.view.KeyEvent; -import android.widget.AdapterView; - -import org.junit.Rule; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.EncryptTextActivity; - -import static androidx.test.espresso.Espresso.onData; -import static androidx.test.espresso.Espresso.onView; -import static androidx.test.espresso.action.ViewActions.click; -import static androidx.test.espresso.action.ViewActions.typeText; -import static androidx.test.espresso.assertion.ViewAssertions.matches; -import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; -import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom; -import static androidx.test.espresso.matcher.ViewMatchers.withId; -import static org.hamcrest.CoreMatchers.allOf; -import static org.sufficientlysecure.keychain.AndroidTestHelpers.importKeysFromResource; -import static org.sufficientlysecure.keychain.actions.CustomActions.tokenEncryptViewAddToken; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withKeyItemId; -import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withKeyToken; - - -//TODO This test is disabled because it needs to be fixed to work with updated code -//@RunWith(AndroidJUnit4.class) -//@LargeTest -public class EncryptKeyCompletionViewTest { - - @Rule - public final ActivityTestRule mActivity - = new ActivityTestRule<>(EncryptTextActivity.class); - - //@Test - public void testTextEncryptDecryptFromToken() throws Exception { - - Intent intent = new Intent(); - intent.putExtra(EncryptTextActivity.EXTRA_ENCRYPTION_KEY_IDS, new long[]{0x9D604D2F310716A3L}); - Activity activity = mActivity.launchActivity(intent); - - // import these two, make sure they're there - importKeysFromResource(activity, "x.sec.asc"); - - // check if the element passed in from intent - onView(ViewMatchers.withId(R.id.recipient_list)).check(matches(withKeyToken(0x9D604D2F310716A3L))); - onView(withId(R.id.recipient_list)).perform(ViewActions.pressKey(KeyEvent.KEYCODE_DEL)); - - // type X, select from list, check if it's there - onView(withId(R.id.recipient_list)).perform(typeText("x")); - onData(withKeyItemId(0x9D604D2F310716A3L)).inRoot(RootMatchers.isPlatformPopup()) - .inAdapterView(allOf(isAssignableFrom(AdapterView.class), - hasDescendant(withId(R.id.key_list_item_name)))).perform(click()); - onView(withId(R.id.recipient_list)).check(matches(withKeyToken(0x9D604D2F310716A3L))); - onView(withId(R.id.recipient_list)).perform(ViewActions.pressKey(KeyEvent.KEYCODE_DEL)); - onView(withId(R.id.recipient_list)).perform(ViewActions.pressKey(KeyEvent.KEYCODE_DEL)); - - // add directly, check if it's there - onView(withId(R.id.recipient_list)).perform(tokenEncryptViewAddToken(0x9D604D2F310716A3L)); - onView(withId(R.id.recipient_list)).check(matches(withKeyToken(0x9D604D2F310716A3L))); - onView(withId(R.id.recipient_list)).perform(ViewActions.pressKey(KeyEvent.KEYCODE_DEL)); - - } - -} diff --git a/extern/MaterialChipsInput/build.gradle b/extern/MaterialChipsInput/build.gradle index 2b8c3f0e2..249bce14b 100644 --- a/extern/MaterialChipsInput/build.gradle +++ b/extern/MaterialChipsInput/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.library' android { - compileSdkVersion 27 + compileSdkVersion 28 defaultConfig { minSdkVersion 15 - targetSdkVersion 27 + targetSdkVersion 28 versionCode 114 versionName "1.1.4" @@ -21,15 +21,10 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - androidTestCompile('androidx.test.espresso:espresso-core:3.1.0', { - exclude group: 'com.android.support', module: 'support-annotations' - }) - compile 'androidx.appcompat:appcompat:1.0.0' - testCompile 'junit:junit:4.12' + implementation 'androidx.appcompat:appcompat:1.1.0' // recycler - compile 'androidx.recyclerview:recyclerview:1.0.0' - compile 'com.beloo.widget:ChipsLayoutManager:0.3.7@aar' + implementation 'androidx.recyclerview:recyclerview:1.1.0' + implementation 'com.beloo.widget:ChipsLayoutManager:0.3.7@aar' } diff --git a/extern/bouncycastle b/extern/bouncycastle index 596f050d0..66dca453c 160000 --- a/extern/bouncycastle +++ b/extern/bouncycastle @@ -1 +1 @@ -Subproject commit 596f050d09dc1a87c09b45e822c673399f41bab1 +Subproject commit 66dca453c37440678760e0c14d4989fb2ddfb771 diff --git a/settings.gradle b/settings.gradle index 3445b9694..ffebe3a12 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,8 +1,6 @@ include ':OpenKeychain' include ':nfcsweetspot' -include ':extern:bouncycastle:core' include ':extern:bouncycastle:pg' -include ':extern:minidns' include ':extern:MaterialChipsInput:library' // Workaround for Android Gradle Plugin 2.0, as described in http://stackoverflow.com/a/36544850