From 2d03965777e99782a0ee7a33e6b90805c79bb07e Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 15 Jun 2015 17:54:53 +0200 Subject: instrument: finish symmetric text encryption test --- .../keychain/EncryptDecryptSymmetricTests.java | 32 +++++- .../keychain/EncryptDecryptTests.java | 2 +- .../sufficientlysecure/keychain/TestHelpers.java | 14 +++ .../keychain/matcher/DrawableMatcher.java | 112 +++++++++++++++++++++ 4 files changed, 156 insertions(+), 4 deletions(-) create mode 100644 OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/DrawableMatcher.java (limited to 'OpenKeychain/src/androidTest') diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/EncryptDecryptSymmetricTests.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/EncryptDecryptSymmetricTests.java index f668472b2..5141a1635 100644 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/EncryptDecryptSymmetricTests.java +++ b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/EncryptDecryptSymmetricTests.java @@ -39,10 +39,14 @@ import static android.support.test.espresso.Espresso.pressBack; 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.matcher.ViewMatchers.isDisplayed; import static android.support.test.espresso.matcher.ViewMatchers.withId; import static android.support.test.espresso.matcher.ViewMatchers.withText; +import static org.hamcrest.CoreMatchers.not; import static org.sufficientlysecure.keychain.TestHelpers.checkSnackbar; +import static org.sufficientlysecure.keychain.TestHelpers.randomString; import static org.sufficientlysecure.keychain.actions.CustomActions.actionOpenDrawer; +import static org.sufficientlysecure.keychain.matcher.DrawableMatcher.withDrawable; @FixMethodOrder(MethodSorters.NAME_ASCENDING) @@ -50,7 +54,7 @@ import static org.sufficientlysecure.keychain.actions.CustomActions.actionOpenDr @LargeTest public class EncryptDecryptSymmetricTests { - public static final String PASSPHRASE = "fn9nf8wnaf"; + public static final String PASSPHRASE = randomString(5, 20); @Rule public final ActivityTestRule mActivity @@ -68,13 +72,14 @@ public class EncryptDecryptSymmetricTests { MainActivity activity = mActivity.getActivity(); + String text = randomString(10, 40); + // navigate to encrypt/decrypt onView(withId(R.id.drawer_layout)).perform(actionOpenDrawer()); onView(ViewMatchers.withText(R.string.nav_encrypt_decrypt)).perform(click()); onView(withId(R.id.encrypt_text)).perform(click()); { - String text = "how much wood"; onView(withId(R.id.encrypt_text_text)).perform(typeText(text)); openActionBarOverflowOrOptionsMenu(getInstrumentation().getTargetContext()); @@ -99,7 +104,28 @@ public class EncryptDecryptSymmetricTests { pressBack(); onView(withId(R.id.decrypt_from_clipboard)).perform(click()); - // TODO fix thing, finish test + { + onView(withId(R.id.passphrase_passphrase)).perform(typeText(PASSPHRASE)); + onView(withText(R.string.btn_unlock)).perform(click()); + + onView(withId(R.id.decrypt_text_plaintext)).check(matches( + withText(text))); + + // TODO write generic status verifier + + onView(withId(R.id.result_encryption_text)).check(matches( + withText(R.string.decrypt_result_encrypted))); + onView(withId(R.id.result_signature_text)).check(matches( + withText(R.string.decrypt_result_no_signature))); + onView(withId(R.id.result_signature_layout)).check(matches( + not(isDisplayed()))); + + onView(withId(R.id.result_encryption_icon)).check(matches( + withDrawable(R.drawable.status_lock_closed_24dp))); + onView(withId(R.id.result_signature_icon)).check(matches( + withDrawable(R.drawable.status_signature_unknown_cutout_24dp))); + + } } diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/EncryptDecryptTests.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/EncryptDecryptTests.java index 01a748172..e93a4c720 100644 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/EncryptDecryptTests.java +++ b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/EncryptDecryptTests.java @@ -92,8 +92,8 @@ public class EncryptDecryptTests { { onView(withId(R.id.passphrase_passphrase)).perform(typeText("x")); - onView(withText(R.string.btn_unlock)).perform(click()); + } } diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/TestHelpers.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/TestHelpers.java index 0adc6b264..da6988678 100644 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/TestHelpers.java +++ b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/TestHelpers.java @@ -1,6 +1,8 @@ package org.sufficientlysecure.keychain; +import java.util.Random; + import android.content.Context; import android.support.annotation.StringRes; @@ -52,4 +54,16 @@ public class TestHelpers { } + 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(); + } + + } diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/DrawableMatcher.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/DrawableMatcher.java new file mode 100644 index 000000000..4996fe19a --- /dev/null +++ b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/DrawableMatcher.java @@ -0,0 +1,112 @@ +/** obtained from + * + * https://github.com/xrigau/droidcon-android-espresso/blob/master/app/src/instrumentTest/java/com/xrigau/droidcon/espresso/helper/DrawableMatcher.java + * + * license pending + */ +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().equals(((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); + } + +} -- cgit v1.2.3