From 804a58e779e8bbb5c8c2d53211626dcfd5556ed7 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 22 Jun 2015 03:16:32 +0200 Subject: [PATCH] instrument: some updates to asymmetric decrypt tests --- OpenKeychain/src/androidTest/assets/ci.png | Bin 0 -> 7230 bytes OpenKeychain/src/androidTest/assets/pa.png | Bin 0 -> 4440 bytes OpenKeychain/src/androidTest/assets/re.png | Bin 0 -> 7085 bytes .../keychain/TestHelpers.java | 40 +- .../actions/OrientationChangeAction.java | 74 ++++ .../ui/AsymmetricFileOperationTests.java | 347 ++++++++++++++++++ .../AsymmetricTextOperationTests.java} | 12 +- .../keychain/ui/MiscFileOperationTests.java | 151 ++++++++ .../keychain/ui/EncryptFilesActivity.java | 5 - .../keychain/ui/EncryptFilesFragment.java | 9 +- 10 files changed, 624 insertions(+), 14 deletions(-) create mode 100644 OpenKeychain/src/androidTest/assets/ci.png create mode 100644 OpenKeychain/src/androidTest/assets/pa.png create mode 100644 OpenKeychain/src/androidTest/assets/re.png create mode 100644 OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/actions/OrientationChangeAction.java create mode 100644 OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/AsymmetricFileOperationTests.java rename OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/{AsymmetricOperationTests.java => ui/AsymmetricTextOperationTests.java} (96%) create mode 100644 OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/MiscFileOperationTests.java diff --git a/OpenKeychain/src/androidTest/assets/ci.png b/OpenKeychain/src/androidTest/assets/ci.png new file mode 100644 index 0000000000000000000000000000000000000000..3a6117082464062bcc098c0ffc05be6c1ed9893d GIT binary patch literal 7230 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 E0W#69RsaA1 literal 0 HcmV?d00001 diff --git a/OpenKeychain/src/androidTest/assets/pa.png b/OpenKeychain/src/androidTest/assets/pa.png new file mode 100644 index 0000000000000000000000000000000000000000..3c6aa7fdaf2574dd582a5ed07ba7d4f692e287d0 GIT binary patch literal 4440 zcmV-e5vT5nP)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00006 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 eZfkR6VQ^(GZ*pgw?mQX*0000tv literal 0 HcmV?d00001 diff --git a/OpenKeychain/src/androidTest/assets/re.png b/OpenKeychain/src/androidTest/assets/re.png new file mode 100644 index 0000000000000000000000000000000000000000..a441bbc87bb5bb29b39898d6b00abced5c5e1709 GIT binary patch literal 7085 zcmV;e8&c$nP)004R=004l4008;_004mL004C`008P>0026e000+nl3&F}00006 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 stream = UncachedKeyRing.fromStream( getInstrumentation().getContext().getAssets().open(name)); @@ -71,6 +78,37 @@ public class TestHelpers { } + 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(); diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/actions/OrientationChangeAction.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/actions/OrientationChangeAction.java new file mode 100644 index 000000000..cdded7d7f --- /dev/null +++ b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/actions/OrientationChangeAction.java @@ -0,0 +1,74 @@ +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 android.support.test.espresso.UiController; +import android.support.test.espresso.ViewAction; +import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry; +import android.support.test.runner.lifecycle.Stage; +import android.view.View; + +import org.hamcrest.Matcher; + +import static android.support.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/ui/AsymmetricFileOperationTests.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/AsymmetricFileOperationTests.java new file mode 100644 index 000000000..7bef6833f --- /dev/null +++ b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/AsymmetricFileOperationTests.java @@ -0,0 +1,347 @@ +/* + * 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 java.io.File; + +import android.annotation.TargetApi; +import android.app.Activity; +import android.app.Instrumentation; +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 android.support.test.InstrumentationRegistry; +import android.support.test.espresso.intent.Intents; +import android.support.test.espresso.intent.rule.IntentsTestRule; +import android.support.test.runner.AndroidJUnit4; +import android.test.suitebuilder.annotation.LargeTest; +import android.widget.AdapterView; + +import org.hamcrest.CoreMatchers; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.TestHelpers; +import org.sufficientlysecure.keychain.service.PassphraseCacheService; +import org.sufficientlysecure.keychain.ui.util.Notify.Style; + +import static android.support.test.InstrumentationRegistry.*; +import static android.support.test.espresso.Espresso.onData; +import static android.support.test.espresso.Espresso.onView; +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.doesNotExist; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.contrib.DrawerActions.openDrawer; +import static android.support.test.espresso.intent.matcher.IntentMatchers.hasAction; +import static android.support.test.espresso.intent.matcher.IntentMatchers.hasCategories; +import static android.support.test.espresso.intent.matcher.IntentMatchers.hasExtra; +import static android.support.test.espresso.intent.matcher.IntentMatchers.hasExtraWithKey; +import static android.support.test.espresso.intent.matcher.IntentMatchers.hasType; +import static android.support.test.espresso.matcher.ViewMatchers.assertThat; +import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; +import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom; +import static android.support.test.espresso.matcher.ViewMatchers.isDescendantOfA; +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.allOf; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.sufficientlysecure.keychain.TestHelpers.checkSnackbar; +import static org.sufficientlysecure.keychain.TestHelpers.getImageNames; +import static org.sufficientlysecure.keychain.TestHelpers.importKeysFromResource; +import static org.sufficientlysecure.keychain.TestHelpers.pickRandom; +import static org.sufficientlysecure.keychain.TestHelpers.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; + + +@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(); + + TestHelpers.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 testTextEncryptDecryptFromToken() 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()); + + handleSaveFileIntent(outputFile); + onView(withId(R.id.encrypt_save)).perform(click()); + + assertThat("output file has been written", true, CoreMatchers.is(outputFile.exists())); + + } + + // go to decrypt from clipboard view + pressBack(); + + handleOpenFileIntentKitKat(outputFile); + onView(withId(R.id.decrypt_files)).perform(click()); + + onView(withId(R.id.decrypt_files_action_decrypt)).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()))); + + } + + } + + 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 handleSaveFileIntent(File file) { + + try { + 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 testTextEncryptDecryptFromKeyView() throws Exception { + + String cleartext = randomString(10, 30); + + // navigate to key list + pressBack(); + + { // encrypt + + // navigate to edit key dialog + onData(withKeyItemId(0x9D604D2F310716A3L)) + .inAdapterView(allOf(isAssignableFrom(AdapterView.class), + isDescendantOfA(withId(R.id.key_list_list)))) + .perform(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))); + + 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(); + pressBack(); + + openDrawer(R.id.drawer_layout); + onView(withText(R.string.nav_encrypt_decrypt)).perform(click()); + 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(withEncryptionStatus(true), withSignatureNone()))); + + } + + pressBack(); + onView(withId(R.id.decrypt_from_clipboard)).perform(click()); + + { // decrypt again, passphrase should be cached + + onView(isRecyclerItemView(R.id.decrypted_files_list, + hasDescendant(withText(R.string.filename_unknown_text)))) + .check(matches(allOf(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()); + + // "delete file" shouldn't be there + onView(withText(R.string.btn_delete_original)).check(doesNotExist()); + + // check if log looks ok + onView(withText(R.string.view_log)).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/AsymmetricOperationTests.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/AsymmetricTextOperationTests.java similarity index 96% rename from OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/AsymmetricOperationTests.java rename to OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/AsymmetricTextOperationTests.java index 246e2dd52..c85dfbaab 100644 --- a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/AsymmetricOperationTests.java +++ b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/AsymmetricTextOperationTests.java @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -package org.sufficientlysecure.keychain; +package org.sufficientlysecure.keychain.ui; import android.app.Activity; @@ -29,6 +29,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.service.PassphraseCacheService; import org.sufficientlysecure.keychain.ui.MainActivity; import org.sufficientlysecure.keychain.ui.util.Notify.Style; @@ -62,7 +63,7 @@ import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withSignatu @RunWith(AndroidJUnit4.class) @LargeTest -public class AsymmetricOperationTests { +public class AsymmetricTextOperationTests { @Rule public final ActivityTestRule mActivity @@ -71,6 +72,7 @@ public class AsymmetricOperationTests { 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; } }; @@ -90,8 +92,6 @@ public class AsymmetricOperationTests { public void testTextEncryptDecryptFromToken() throws Exception { // navigate to 'encrypt text' - openDrawer(R.id.drawer_layout); - onView(withText(R.string.nav_encrypt_decrypt)).perform(click()); onView(withId(R.id.encrypt_text)).perform(click()); String cleartext = randomString(10, 30); @@ -130,6 +130,8 @@ public class AsymmetricOperationTests { String cleartext = randomString(10, 30); + pressBack(); + { // encrypt // navigate to edit key dialog @@ -185,8 +187,6 @@ public class AsymmetricOperationTests { String cleartext = randomString(10, 30); // navigate to 'encrypt text' - openDrawer(R.id.drawer_layout); - onView(withText(R.string.nav_encrypt_decrypt)).perform(click()); onView(withId(R.id.encrypt_text)).perform(click()); { // sign diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/MiscFileOperationTests.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/MiscFileOperationTests.java new file mode 100644 index 000000000..8d8437561 --- /dev/null +++ b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/ui/MiscFileOperationTests.java @@ -0,0 +1,151 @@ +/* + * 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 java.io.File; + +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 android.support.test.espresso.intent.Intents; +import android.support.test.espresso.intent.rule.IntentsTestRule; +import android.support.test.runner.AndroidJUnit4; +import android.test.suitebuilder.annotation.LargeTest; +import android.widget.AdapterView; + +import org.hamcrest.CoreMatchers; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.TestHelpers; +import org.sufficientlysecure.keychain.service.PassphraseCacheService; +import org.sufficientlysecure.keychain.ui.util.Notify.Style; + +import static android.support.test.InstrumentationRegistry.getInstrumentation; +import static android.support.test.espresso.Espresso.onData; +import static android.support.test.espresso.Espresso.onView; +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.doesNotExist; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.contrib.DrawerActions.openDrawer; +import static android.support.test.espresso.intent.matcher.IntentMatchers.hasAction; +import static android.support.test.espresso.intent.matcher.IntentMatchers.hasCategories; +import static android.support.test.espresso.intent.matcher.IntentMatchers.hasExtra; +import static android.support.test.espresso.intent.matcher.IntentMatchers.hasExtraWithKey; +import static android.support.test.espresso.intent.matcher.IntentMatchers.hasType; +import static android.support.test.espresso.matcher.ViewMatchers.assertThat; +import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; +import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom; +import static android.support.test.espresso.matcher.ViewMatchers.isDescendantOfA; +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.allOf; +import static org.hamcrest.CoreMatchers.hasItem; +import static org.sufficientlysecure.keychain.TestHelpers.checkSnackbar; +import static org.sufficientlysecure.keychain.TestHelpers.getImageNames; +import static org.sufficientlysecure.keychain.TestHelpers.importKeysFromResource; +import static org.sufficientlysecure.keychain.TestHelpers.pickRandom; +import static org.sufficientlysecure.keychain.TestHelpers.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; +import static org.sufficientlysecure.keychain.matcher.DrawableMatcher.withDrawable; + + +@RunWith(AndroidJUnit4.class) +@LargeTest +public class MiscFileOperationTests { + + @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(); + + TestHelpers.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 testDecryptNonPgpFile() throws Exception { + + // decrypt any non-pgp file + File file = pickRandom(getImageNames()); + handleOpenFileIntentKitKat(file); + onView(withId(R.id.decrypt_files)).perform(click()); + + onView(withId(R.id.decrypt_files_action_decrypt)).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 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) + ); + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java index 4d23ba9f8..d51b6e0ff 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesActivity.java @@ -50,14 +50,9 @@ public class EncryptFilesActivity extends EncryptActivity { Intent intent = getIntent(); String action = intent.getAction(); - Bundle extras = intent.getExtras(); String type = intent.getType(); ArrayList uris = new ArrayList<>(); - if (extras == null) { - extras = new Bundle(); - } - if (intent.getData() != null) { uris.add(intent.getData()); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java index c14f957f7..897770411 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptFilesFragment.java @@ -78,7 +78,7 @@ public class EncryptFilesFragment public static final String ARG_USE_ASCII_ARMOR = "use_ascii_armor"; public static final String ARG_URIS = "uris"; - private static final int REQUEST_CODE_INPUT = 0x00007003; + public static final int REQUEST_CODE_INPUT = 0x00007003; private static final int REQUEST_CODE_OUTPUT = 0x00007007; private boolean mUseArmor; @@ -229,8 +229,13 @@ public class EncryptFilesFragment String targetName = (mEncryptFilenames ? "1" : FileHelper.getFilename(getActivity(), model.inputUri)) + (mUseArmor ? Constants.FILE_EXTENSION_ASC : Constants.FILE_EXTENSION_PGP_MAIN); + Uri inputUri = model.inputUri; + saveDocumentIntent(targetName, inputUri); + } + + private void saveDocumentIntent(String targetName, Uri inputUri) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { - File file = new File(model.inputUri.getPath()); + File file = new File(inputUri.getPath()); File parentDir = file.exists() ? file.getParentFile() : Constants.Path.APP_DIR; File targetFile = new File(parentDir, targetName); FileHelper.saveFile(this, getString(R.string.title_encrypt_to_file),