Merge branch 'v/instrument' into v/multi-decrypt
Conflicts: .travis.yml OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/CreateKeyActivityTest.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpDecryptVerify.java
This commit is contained in:
1032
OpenKeychain/src/androidTest/assets/valodim.pub.asc
Normal file
1032
OpenKeychain/src/androidTest/assets/valodim.pub.asc
Normal file
File diff suppressed because it is too large
Load Diff
156
OpenKeychain/src/androidTest/assets/x.sec.asc
Normal file
156
OpenKeychain/src/androidTest/assets/x.sec.asc
Normal file
@@ -0,0 +1,156 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQINBFTxJOIBEACpXpXjz5ivyR/uWJexJXZrLHrvBRcivQSxzvy5Owdun8MGOxzo
|
||||
YTPAJzskZH4Gg9MIQj9puUke8A59o9KtNMAd3Szp6aQs3lv/eGOw0DUe6g8a6kJ+
|
||||
oQsHMYYLnyuYrOvQrBewKhh4FynkryvUZCL25dgrMHeTeMAeslCscdT6JYd2gxgi
|
||||
o0+Bn8R6BonS7hTZStfAOYB0SO7X+7R0CpPsMiHtNZASzLRkk53dB9AO6m81CurP
|
||||
qh1oPjc7j1QIiwCszSD8IxuR3fH6nyUlMtqx/mRmKNlbIYnr3sN5VAMp7THq/Qjt
|
||||
9XDs1XHBE+0H+yg7K4fPamSJsxy9zPq/rA9vy4pQIMzxugxeWEn4OPWtguRSYtI1
|
||||
WA+Ki93QJ+DVRlpMvz/MA71ZkvWUHpFnIssU52NdHZrIZ21KCo7PiPRY9tQkVhz5
|
||||
S39a8npSeCIwZ9bH3UGKrRyPkhal59rjPqhZky1X+O2iTfbbFrPE+I4b46pWX9XU
|
||||
UgXDnUh8Qeymhh0f1DTcbquW2nwU/R1quKjw/TCZQxKnkAzCXsVFk2QoIG1qDVrU
|
||||
YlKXTXoYaRfzhMSYSvh7JHqdldB+MyKAbXpLtZsYIlLkuqe/KI0IPfO69ajDxLOr
|
||||
+wTtuA9T1SICGmQkjYkQiqVy4y7vDW4Zw143sPXreZhiBbLBoWAIJ/JcbQARAQAB
|
||||
tAVYIDx4PokCNwQTAQoAIQULCQgHAwYVCgkLCAMEFgIDAQIZAQWCVPEk4wKeAQKb
|
||||
AQAKCRCdYE0vMQcWo/TGD/9SEfE7LxWw4pPNTpVTECDztpLGrj7kCr0anO6XnCqL
|
||||
3OYoZz5vZvKBmunoPT7VqerQIZCnhB0b0ZOI+l51J03Xwvfy1+MIQCnZz++JY94B
|
||||
h5dv3QAj8WUJJ6KfKrAxoXGU67mNhW5oe3mXQd3/a0JjmjV2yzFFOS4edyWPQal9
|
||||
lY6MpOKfEIiD6uRqh8A1A9jAstJ9c5XHVtuBv265DEK5tMyAU3cmtm0pEzgmvPoG
|
||||
kxo1vDAhP9GKb+DcBrB6XuZ7Kahl+kDpEhmuI6drxJBhez169aE43dK7G3X1W78f
|
||||
OyO0C4jWAy1kVj4aYT4qgJj8TwRoAwlzX5RqmK4RW17sX3nOlff/FQclepawOrU+
|
||||
LO5ZgbQ4qG2yDJSJ+tcS2fIO1MoI5vPa7DIVEpMM7DbrPYVy0Ix/xv80MwKQhnWs
|
||||
P5tLRGuJ7JbKPzqvBtG7xWow5isOMkqeBkU0yUr59tAtHwM6c3Vi2at9YBiraqBY
|
||||
3mgEukIuNpSuhFSBhniVUovVGgj8LCLDL+mpuc9+HUzYWJKGks+eGY0Od+dJjgh+
|
||||
wXQk0rTTkY80kKpIjREDOVuPRhsw5OYb63fbiaYwormPx4pXv2mitOYNAXy3YNpR
|
||||
Xl5MvObYLQugpqtyjpijyyANbsHKWwClkL/vxnbcfRXF307NQGSwhs3gKpSuovVE
|
||||
edEkI2QBI0VncGdwaWQ6QGRuczp0ZXN0Lm11Z2VuZ3VpbGQuY29tiQIcBBMBCgAG
|
||||
BYJU9KuzAAoJEJ1gTS8xBxajnPEP+gL3MasL9GcXt0c93QkQsRay8IMCspM+Qt/X
|
||||
rfoUSJb41V4nqeyumX/kRmY7/eMZJnxIJgn8aWmRjiPhasUMBfeXmm4RAmwHEkFP
|
||||
6nw288dHIlKgRaAMwfs44thKxPKTkscLiSqbmrRhLULW840pIZkgtOLmhH2tiaa7
|
||||
w/hgDCMgHfwZaSlQkEDfvAef7i61itNdBlL0e0CelzNL0Uc5P6b/Nvn5uWlrLIHZ
|
||||
evOx8dswhmwz25D7KZQPh91JpAqoLk5hj3/DAbVxeUFK/Zt9o/bu+ij57qSfRif3
|
||||
HlLydH98FFcetqLbGDt1/Eiea3tpqjK5Xgf+HOppQo2MpOCP64xNejGWnKx6M7yF
|
||||
A/yiI4Ahe4uP9+SXar0FPLGXAfyc/pSrRN94dY+iXpWPCSlNRNAOyr1mxPCvw9MM
|
||||
C5wYnfLLSWUMPYv9rQyr1pvYyxe2r0Fla6JAkRy5nMnR1RdorwafeMcyQi3nllBS
|
||||
S0wzmagus1W2qqRbbOR8J5CXkkjbw9vV0vXFnCHq93ms9Ebnhr5rNzVndKnxVCmK
|
||||
hftW7gFz8Qz3tG66eSWA/6VrRvfUNfR5cUBpVOARqxqYz7OPrGg0Lkfw+JPQX8v/
|
||||
WMIfM6Jsj/koJmOb2y/h0rJ+iTBofPCoGONKIzlOK5c8bhSmU/27KX1xBacTgN9Q
|
||||
hlulIbZs0SsqZAAS1odwZ3BpZCtjb29raWU6QGRuczp0ZXN0Lm11Z2VuZ3VpbGQu
|
||||
Y29tiQIcBBMBCgAGBYJU901MAAoJEJ1gTS8xBxajHKAP/3WDeUfBkuq50v3E8SBx
|
||||
qDHXomPncNOccRPS1/DYwxVp5JYE8NsFW2rlmeJiy4Rhm4MnptUFUTPMBfYOcHvT
|
||||
oWr/3Gz0y5ik5oiPC5hAXWCPrNkdtgBugBByL+0+w2PWKQqwBIc9ef+7aIh28dKn
|
||||
6zr71Au+DXJKqYz/jOqY3IJGzBkydxOPSy83WNPm9OR/zfhCOoCTDAy+0TGxYgjW
|
||||
Idi4k4yDRWhAeF+GqJRuDf1RKZxPL1MjwhX0Lv4ndR+V3sECRVh6HRIBGYYti8kU
|
||||
0Q9jdbYjU+guestyyvsWQBOaGRP+gGQY+fYdHb2YUK6jMcndPxbRonjaRY5Bcc0J
|
||||
NAYAqFv/WyR7hd4SWXI8Zg3u+GV7x8ZbnUOwfvXBVvZohbycpoT7WVOPRhQ2CQ5P
|
||||
uS2E5QaoA6fUfH2qUAaxlvnfMRPL9E1svIEFXMtf1GqO6hzzJWV6Qw59HODTy568
|
||||
StloM6IVnlolJfxf7+aEQx+KrmxJqVVWlbZ5u5gzQa+Mak0N5F6m8w4VftyHT0W6
|
||||
RinNh3IGbk64+uXYzAUhJ6badfXrrxTP0wkjPPPjNC/BKfPCzYhZnyGLCuFwlOqE
|
||||
o1Nq6qMzSHOlxR08ycX0MLNEfWsqu2CV8YGLYThejOr8JSjyXM3ANHNB+AZ5/eeY
|
||||
AGUc5XgxTbq/MpnytiBzaZfw0Tw7ZAAS1odwZ3BpZCtjb29raWU6Z2VuZXJpY0Bo
|
||||
dHRwczovL211Z2VuZ3VpbGQuY29tL3BncGtleS50eHSJAhwEEwEIAAYFglT4KOIA
|
||||
CgkQnWBNLzEHFqOZJQ//UL+/ZfikmVA8DDIbbd8beIgJ0uRZgQ4aVuxRNiWhxQbl
|
||||
5KPQaiztrwr3ESgyf3HjjUyGhg5/UP+ObvloCqcwCphSrBNxHiEp31jLin7QfWLp
|
||||
vzPOjtMJNEeq3yeXq+YpHw2VZ+nod+XD785YtLBqq1SipNSZEifRYnsLhqQOj6cB
|
||||
t0F2RLBm5afLbd4KjelT7W7229lYlGJkoQEwrmVYASiMfeBDBnHJ1Xgp1P0dm1gS
|
||||
ERVSzV2qW6w0/psOHq4cnq4XWSn/IRW3UYfHIDDZJG125keYoaJAbBnzC+OO4eV2
|
||||
KheY5dkmaeT0RmgzpEyJq5PRDNpnoXvSYuC9KGiNTbCiQ3liJnUJslbzDwvTyTfa
|
||||
wxUba4dXhpcSE8mjXa/9/vMJER5yW0zzkSa+fjIIZcL0PQqlTeDBzFMSA9Ut9Y+m
|
||||
6vdGwelIeyb38dWvsDC1NUUR2pydTsRtFM1o7jUtGoovQlLh5/9x/YDh8vqpzip3
|
||||
L5SSvN4RdXN4P+EZor4xfi0PVbHoDZusxyPfKEFlCnX6k9qEaWplacLbl8M8mtpv
|
||||
++3vYVW6hA3rK/6XdftFDJpbmj+zTXvrATE/lvPcJHiswiuMLx9BPoEiv1MGXTyE
|
||||
6TxB5H7L1eCQWfbZYnkEWiuXlfDyofvDfufiGTsBAQzN3ePuhYUNznUB+1syD4E=
|
||||
=Sxs8
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
-----BEGIN PGP PRIVATE KEY BLOCK-----
|
||||
|
||||
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
|
||||
=AYKY
|
||||
-----END PGP PRIVATE KEY BLOCK-----
|
||||
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Vincent Breitmoser <look@my.amazin.horse>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.support.test.rule.ActivityTestRule;
|
||||
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.service.PassphraseCacheService;
|
||||
import org.sufficientlysecure.keychain.ui.MainActivity;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
||||
|
||||
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.matches;
|
||||
import static android.support.test.espresso.contrib.DrawerActions.openDrawer;
|
||||
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.not;
|
||||
import static org.sufficientlysecure.keychain.TestHelpers.checkSnackbar;
|
||||
import static org.sufficientlysecure.keychain.TestHelpers.importKeysFromResource;
|
||||
import static org.sufficientlysecure.keychain.TestHelpers.randomString;
|
||||
import static org.sufficientlysecure.keychain.actions.CustomActions.tokenEncryptViewAddToken;
|
||||
import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withKeyItemId;
|
||||
import static org.sufficientlysecure.keychain.matcher.DrawableMatcher.withDrawable;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@LargeTest
|
||||
public class AsymmetricOperationTests {
|
||||
|
||||
@Rule
|
||||
public final ActivityTestRule<MainActivity> mActivity
|
||||
= new ActivityTestRule<MainActivity>(MainActivity.class) {
|
||||
@Override
|
||||
protected Intent getActivityIntent() {
|
||||
Intent intent = super.getActivityIntent();
|
||||
intent.putExtra(MainActivity.EXTRA_SKIP_FIRST_TIME, true);
|
||||
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'
|
||||
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);
|
||||
|
||||
{ // encrypt
|
||||
|
||||
// the EncryptKeyCompletionView is tested individually
|
||||
onView(withId(R.id.recipient_list)).perform(tokenEncryptViewAddToken(0x9D604D2F310716A3L));
|
||||
|
||||
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(withId(R.id.decrypt_text_plaintext)).check(matches(
|
||||
withText(cleartext)));
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTextEncryptDecryptFromKeyView() throws Exception {
|
||||
|
||||
String cleartext = randomString(10, 30);
|
||||
|
||||
{ // 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());
|
||||
|
||||
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(withId(R.id.decrypt_text_plaintext)).check(matches(
|
||||
withText(cleartext)));
|
||||
|
||||
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)));
|
||||
|
||||
}
|
||||
|
||||
pressBack();
|
||||
onView(withId(R.id.decrypt_from_clipboard)).perform(click());
|
||||
|
||||
{ // decrypt again, passphrase should be cached
|
||||
|
||||
onView(withId(R.id.decrypt_text_plaintext)).check(matches(
|
||||
withText(cleartext)));
|
||||
|
||||
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)));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignVerify() throws Exception {
|
||||
|
||||
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
|
||||
|
||||
onView(withId(R.id.encrypt_copy)).perform(click());
|
||||
checkSnackbar(Style.ERROR, R.string.error_empty_text);
|
||||
|
||||
// navigate to edit key dialog
|
||||
onView(withId(R.id.sign)).perform(click());
|
||||
onData(withKeyItemId(0x9D604D2F310716A3L))
|
||||
.inAdapterView(isAssignableFrom(AdapterView.class))
|
||||
.perform(click());
|
||||
|
||||
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(withId(R.id.decrypt_text_plaintext)).check(matches(
|
||||
// startsWith because there may be extra newlines
|
||||
withText(CoreMatchers.startsWith(cleartext))));
|
||||
|
||||
onView(withId(R.id.result_encryption_text)).check(matches(
|
||||
withText(R.string.decrypt_result_not_encrypted)));
|
||||
onView(withId(R.id.result_signature_text)).check(matches(
|
||||
withText(R.string.decrypt_result_signature_secret)));
|
||||
onView(withId(R.id.result_signature_layout)).check(matches(
|
||||
isDisplayed()));
|
||||
|
||||
onView(withId(R.id.result_encryption_icon)).check(matches(
|
||||
withDrawable(R.drawable.status_lock_open_24dp)));
|
||||
onView(withId(R.id.result_signature_icon)).check(matches(
|
||||
withDrawable(R.drawable.status_signature_verified_cutout_24dp)));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,11 +17,16 @@
|
||||
|
||||
package org.sufficientlysecure.keychain;
|
||||
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.test.suitebuilder.annotation.LargeTest;
|
||||
import android.text.method.HideReturnsTransformationMethod;
|
||||
import android.text.method.PasswordTransformationMethod;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.sufficientlysecure.keychain.ui.CreateKeyActivity;
|
||||
|
||||
import static android.support.test.espresso.Espresso.onView;
|
||||
@@ -40,6 +45,7 @@ import static org.hamcrest.Matchers.allOf;
|
||||
import static org.sufficientlysecure.keychain.matcher.EditTextMatchers.withError;
|
||||
import static org.sufficientlysecure.keychain.matcher.EditTextMatchers.withTransformationMethod;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@LargeTest
|
||||
public class CreateKeyActivityTest extends ActivityInstrumentationTestCase2<CreateKeyActivity> {
|
||||
|
||||
@@ -52,9 +58,10 @@ public class CreateKeyActivityTest extends ActivityInstrumentationTestCase2<Crea
|
||||
super(CreateKeyActivity.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
injectInstrumentation(InstrumentationRegistry.getInstrumentation());
|
||||
getActivity();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Vincent Breitmoser <look@my.amazin.horse>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.support.test.rule.ActivityTestRule;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.test.suitebuilder.annotation.LargeTest;
|
||||
import android.widget.AdapterView;
|
||||
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
|
||||
import org.sufficientlysecure.keychain.ui.MainActivity;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
||||
|
||||
import static android.support.test.espresso.Espresso.onData;
|
||||
import static android.support.test.espresso.Espresso.onView;
|
||||
import static android.support.test.espresso.action.ViewActions.click;
|
||||
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.withId;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static org.hamcrest.CoreMatchers.allOf;
|
||||
import static org.sufficientlysecure.keychain.TestHelpers.checkSnackbar;
|
||||
import static org.sufficientlysecure.keychain.TestHelpers.importKeysFromResource;
|
||||
import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withKeyItemId;
|
||||
|
||||
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@LargeTest
|
||||
public class EditKeyTest {
|
||||
|
||||
@Rule
|
||||
public final ActivityTestRule<MainActivity> mActivity
|
||||
= new ActivityTestRule<MainActivity>(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();
|
||||
|
||||
new KeychainDatabase(activity).clearDatabase();
|
||||
|
||||
// import key for testing, get a stable initial state
|
||||
importKeysFromResource(activity, "x.sec.asc");
|
||||
|
||||
// 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.menu_key_view_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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Vincent Breitmoser <look@my.amazin.horse>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain;
|
||||
|
||||
|
||||
import android.content.Intent;
|
||||
import android.support.test.espresso.matcher.ViewMatchers;
|
||||
import android.support.test.rule.ActivityTestRule;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.test.suitebuilder.annotation.LargeTest;
|
||||
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.sufficientlysecure.keychain.ui.MainActivity;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
||||
|
||||
import static android.support.test.InstrumentationRegistry.getInstrumentation;
|
||||
import static android.support.test.espresso.Espresso.onView;
|
||||
import static android.support.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu;
|
||||
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.contrib.DrawerActions.openDrawer;
|
||||
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.matcher.DrawableMatcher.withDrawable;
|
||||
|
||||
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@LargeTest
|
||||
public class EncryptDecryptSymmetricTests {
|
||||
|
||||
public static final String PASSPHRASE = randomString(5, 20);
|
||||
|
||||
@Rule
|
||||
public final ActivityTestRule<MainActivity> mActivity
|
||||
= new ActivityTestRule<MainActivity>(MainActivity.class) {
|
||||
@Override
|
||||
protected Intent getActivityIntent() {
|
||||
Intent intent = super.getActivityIntent();
|
||||
intent.putExtra(MainActivity.EXTRA_SKIP_FIRST_TIME, true);
|
||||
return intent;
|
||||
}
|
||||
};
|
||||
|
||||
@Test
|
||||
public void testSymmetricTextEncryptDecrypt() throws Exception {
|
||||
|
||||
MainActivity activity = mActivity.getActivity();
|
||||
|
||||
String text = randomString(10, 30);
|
||||
|
||||
// navigate to encrypt/decrypt
|
||||
openDrawer(R.id.drawer_layout);
|
||||
onView(ViewMatchers.withText(R.string.nav_encrypt_decrypt)).perform(click());
|
||||
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(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)));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Vincent Breitmoser <look@my.amazin.horse>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.support.test.espresso.action.ViewActions;
|
||||
import android.support.test.espresso.matcher.RootMatchers;
|
||||
import android.support.test.rule.ActivityTestRule;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.test.suitebuilder.annotation.LargeTest;
|
||||
import android.view.KeyEvent;
|
||||
import android.widget.AdapterView;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.sufficientlysecure.keychain.ui.EncryptTextActivity;
|
||||
|
||||
import static android.support.test.espresso.Espresso.onData;
|
||||
import static android.support.test.espresso.Espresso.onView;
|
||||
import static android.support.test.espresso.action.ViewActions.click;
|
||||
import static android.support.test.espresso.action.ViewActions.typeText;
|
||||
import static android.support.test.espresso.assertion.ViewAssertions.matches;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static org.hamcrest.CoreMatchers.allOf;
|
||||
import static org.sufficientlysecure.keychain.TestHelpers.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;
|
||||
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@LargeTest
|
||||
public class EncryptKeyCompletionViewTest {
|
||||
|
||||
@Rule
|
||||
public final ActivityTestRule<EncryptTextActivity> 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(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));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.sufficientlysecure.keychain;
|
||||
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Vincent Breitmoser <look@my.amazin.horse>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain;
|
||||
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.StringRes;
|
||||
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
|
||||
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing.IteratorWithIOThrow;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
||||
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
||||
|
||||
import static android.support.test.InstrumentationRegistry.getInstrumentation;
|
||||
import static android.support.test.espresso.Espresso.onView;
|
||||
import static android.support.test.espresso.assertion.ViewAssertions.matches;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withClassName;
|
||||
import static android.support.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static org.sufficientlysecure.keychain.matcher.CustomMatchers.withSnackbarLineColor;
|
||||
|
||||
|
||||
public class TestHelpers {
|
||||
|
||||
|
||||
public static void checkSnackbar(Style style, @StringRes Integer text) {
|
||||
|
||||
onView(withClassName(CoreMatchers.endsWith("Snackbar")))
|
||||
.check(matches(withSnackbarLineColor(style.mLineColor)));
|
||||
|
||||
if (text != null) {
|
||||
onView(withClassName(CoreMatchers.endsWith("Snackbar")))
|
||||
.check(matches(hasDescendant(withText(text))));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void importKeysFromResource(Context context, String name) throws Exception {
|
||||
IteratorWithIOThrow<UncachedKeyRing> stream = UncachedKeyRing.fromStream(
|
||||
getInstrumentation().getContext().getAssets().open(name));
|
||||
|
||||
ProviderHelper helper = new ProviderHelper(context);
|
||||
while(stream.hasNext()) {
|
||||
UncachedKeyRing ring = stream.next();
|
||||
if (ring.isSecret()) {
|
||||
helper.saveSecretKeyRing(ring, new ProgressScaler());
|
||||
} else {
|
||||
helper.savePublicKeyRing(ring, new ProgressScaler());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Vincent Breitmoser <look@my.amazin.horse>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.actions;
|
||||
|
||||
|
||||
import android.support.test.espresso.UiController;
|
||||
import android.support.test.espresso.ViewAction;
|
||||
import android.support.test.espresso.matcher.ViewMatchers;
|
||||
import android.support.v4.view.GravityCompat;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.view.View;
|
||||
|
||||
import com.tokenautocomplete.TokenCompleteTextView;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.KeyAdapter;
|
||||
|
||||
import static android.support.test.InstrumentationRegistry.getTargetContext;
|
||||
|
||||
|
||||
public abstract class CustomActions {
|
||||
|
||||
public static ViewAction tokenEncryptViewAddToken(long keyId) throws Exception {
|
||||
CanonicalizedPublicKeyRing ring =
|
||||
new ProviderHelper(getTargetContext()).getCanonicalizedPublicKeyRing(keyId);
|
||||
final Object item = new KeyAdapter.KeyItem(ring);
|
||||
|
||||
return new ViewAction() {
|
||||
@Override
|
||||
public Matcher<View> 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<View> 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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Vincent Breitmoser <look@my.amazin.horse>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.matcher;
|
||||
|
||||
|
||||
import android.support.annotation.ColorRes;
|
||||
import android.support.test.espresso.matcher.BoundedMatcher;
|
||||
import android.view.View;
|
||||
|
||||
import com.nispok.snackbar.Snackbar;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.sufficientlysecure.keychain.EncryptKeyCompletionViewTest;
|
||||
import org.sufficientlysecure.keychain.ui.adapter.KeyAdapter.KeyItem;
|
||||
import org.sufficientlysecure.keychain.ui.widget.EncryptKeyCompletionView;
|
||||
|
||||
import static android.support.test.internal.util.Checks.checkNotNull;
|
||||
|
||||
|
||||
public abstract class CustomMatchers {
|
||||
|
||||
public static Matcher<View> withSnackbarLineColor(@ColorRes final int colorRes) {
|
||||
return new BoundedMatcher<View, Snackbar>(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<Object> withKeyItemId(final long keyId) {
|
||||
return new BoundedMatcher<Object, KeyItem>(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<View> withKeyToken(@ColorRes final long keyId) {
|
||||
return new BoundedMatcher<View, EncryptKeyCompletionView>(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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Xavi Rigau <xrigau@gmail.com>
|
||||
* Copyright (C) 2015 Vincent Breitmoser <look@my.amazin.horse>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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<View> {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
* Copyright (C) 2015 Vincent Breitmoser <look@my.amazin.horse>
|
||||
*
|
||||
* 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
|
||||
|
||||
Reference in New Issue
Block a user