add some unit tests for RecipientLoader
This commit is contained in:
parent
fca4630177
commit
c2171b5161
2 changed files with 161 additions and 15 deletions
|
@ -85,6 +85,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
|
||||||
private final Uri contactUri;
|
private final Uri contactUri;
|
||||||
private final Uri lookupKeyUri;
|
private final Uri lookupKeyUri;
|
||||||
private final String cryptoProvider;
|
private final String cryptoProvider;
|
||||||
|
private final ContentResolver contentResolver;
|
||||||
|
|
||||||
private List<Recipient> cachedRecipients;
|
private List<Recipient> cachedRecipients;
|
||||||
private ForceLoadContentObserver observerContact, observerKey;
|
private ForceLoadContentObserver observerContact, observerKey;
|
||||||
|
@ -97,6 +98,8 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
|
||||||
this.addresses = null;
|
this.addresses = null;
|
||||||
this.contactUri = null;
|
this.contactUri = null;
|
||||||
this.cryptoProvider = cryptoProvider;
|
this.cryptoProvider = cryptoProvider;
|
||||||
|
|
||||||
|
contentResolver = context.getContentResolver();
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecipientLoader(Context context, String cryptoProvider, Address... addresses) {
|
public RecipientLoader(Context context, String cryptoProvider, Address... addresses) {
|
||||||
|
@ -106,6 +109,8 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
|
||||||
this.contactUri = null;
|
this.contactUri = null;
|
||||||
this.cryptoProvider = cryptoProvider;
|
this.cryptoProvider = cryptoProvider;
|
||||||
this.lookupKeyUri = null;
|
this.lookupKeyUri = null;
|
||||||
|
|
||||||
|
contentResolver = context.getContentResolver();
|
||||||
}
|
}
|
||||||
|
|
||||||
public RecipientLoader(Context context, String cryptoProvider, Uri contactUri, boolean isLookupKey) {
|
public RecipientLoader(Context context, String cryptoProvider, Uri contactUri, boolean isLookupKey) {
|
||||||
|
@ -115,6 +120,8 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
|
||||||
this.contactUri = isLookupKey ? null : contactUri;
|
this.contactUri = isLookupKey ? null : contactUri;
|
||||||
this.lookupKeyUri = isLookupKey ? contactUri : null;
|
this.lookupKeyUri = isLookupKey ? contactUri : null;
|
||||||
this.cryptoProvider = cryptoProvider;
|
this.cryptoProvider = cryptoProvider;
|
||||||
|
|
||||||
|
contentResolver = context.getContentResolver();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -154,7 +161,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
|
||||||
Cursor cursor;
|
Cursor cursor;
|
||||||
try {
|
try {
|
||||||
Uri queryUri = Uri.parse("content://" + cryptoProvider + ".provider.exported/autocrypt_status");
|
Uri queryUri = Uri.parse("content://" + cryptoProvider + ".provider.exported/autocrypt_status");
|
||||||
cursor = getContext().getContentResolver().query(queryUri, PROJECTION_CRYPTO_ADDRESSES, null,
|
cursor = contentResolver.query(queryUri, PROJECTION_CRYPTO_ADDRESSES, null,
|
||||||
new String[] { "%" + query + "%" }, null);
|
new String[] { "%" + query + "%" }, null);
|
||||||
|
|
||||||
if (cursor == null) {
|
if (cursor == null) {
|
||||||
|
@ -195,7 +202,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
|
||||||
|
|
||||||
private void fillContactDataFromEmailContentUri(Uri contactUri, List<Recipient> recipients,
|
private void fillContactDataFromEmailContentUri(Uri contactUri, List<Recipient> recipients,
|
||||||
Map<String, Recipient> recipientMap) {
|
Map<String, Recipient> recipientMap) {
|
||||||
Cursor cursor = getContext().getContentResolver().query(contactUri, PROJECTION, null, null, null);
|
Cursor cursor = contentResolver.query(contactUri, PROJECTION, null, null, null);
|
||||||
|
|
||||||
if (cursor == null) {
|
if (cursor == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -207,14 +214,14 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
|
||||||
private void fillContactDataFromLookupKey(Uri lookupKeyUri, List<Recipient> recipients,
|
private void fillContactDataFromLookupKey(Uri lookupKeyUri, List<Recipient> recipients,
|
||||||
Map<String, Recipient> recipientMap) {
|
Map<String, Recipient> recipientMap) {
|
||||||
// We could use the contact id from the URI directly, but getting it from the lookup key is safer
|
// We could use the contact id from the URI directly, but getting it from the lookup key is safer
|
||||||
Uri contactContentUri = Contacts.lookupContact(getContext().getContentResolver(), lookupKeyUri);
|
Uri contactContentUri = Contacts.lookupContact(contentResolver, lookupKeyUri);
|
||||||
if (contactContentUri == null) {
|
if (contactContentUri == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String contactIdStr = getContactIdFromContactUri(contactContentUri);
|
String contactIdStr = getContactIdFromContactUri(contactContentUri);
|
||||||
|
|
||||||
Cursor cursor = getContext().getContentResolver().query(
|
Cursor cursor = contentResolver.query(
|
||||||
ContactsContract.CommonDataKinds.Email.CONTENT_URI,
|
ContactsContract.CommonDataKinds.Email.CONTENT_URI,
|
||||||
PROJECTION, ContactsContract.CommonDataKinds.Email.CONTACT_ID + "=?",
|
PROJECTION, ContactsContract.CommonDataKinds.Email.CONTACT_ID + "=?",
|
||||||
new String[] { contactIdStr }, null);
|
new String[] { contactIdStr }, null);
|
||||||
|
@ -236,7 +243,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
|
||||||
|
|
||||||
Uri queryUriForNickname = ContactsContract.Data.CONTENT_URI;
|
Uri queryUriForNickname = ContactsContract.Data.CONTENT_URI;
|
||||||
|
|
||||||
return getContext().getContentResolver().query(queryUriForNickname,
|
return contentResolver.query(queryUriForNickname,
|
||||||
PROJECTION_NICKNAME,
|
PROJECTION_NICKNAME,
|
||||||
ContactsContract.CommonDataKinds.Nickname.NAME + " LIKE ? AND " +
|
ContactsContract.CommonDataKinds.Nickname.NAME + " LIKE ? AND " +
|
||||||
Data.MIMETYPE + " = ?",
|
Data.MIMETYPE + " = ?",
|
||||||
|
@ -261,7 +268,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
|
||||||
private void registerContentObserver() {
|
private void registerContentObserver() {
|
||||||
if (observerContact != null) {
|
if (observerContact != null) {
|
||||||
observerContact = new ForceLoadContentObserver();
|
observerContact = new ForceLoadContentObserver();
|
||||||
getContext().getContentResolver().registerContentObserver(Email.CONTENT_URI, false, observerContact);
|
contentResolver.registerContentObserver(Email.CONTENT_URI, false, observerContact);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,8 +278,6 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
|
||||||
|
|
||||||
boolean hasContact = false;
|
boolean hasContact = false;
|
||||||
|
|
||||||
final ContentResolver contentResolver = getContext().getContentResolver();
|
|
||||||
|
|
||||||
Uri queryUri = Email.CONTENT_URI;
|
Uri queryUri = Email.CONTENT_URI;
|
||||||
|
|
||||||
Cursor nicknameCursor = getNicknameCursor(nickname);
|
Cursor nicknameCursor = getNicknameCursor(nickname);
|
||||||
|
@ -303,8 +308,6 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
|
||||||
|
|
||||||
private boolean fillContactDataFromNameAndEmail(String query, List<Recipient> recipients,
|
private boolean fillContactDataFromNameAndEmail(String query, List<Recipient> recipients,
|
||||||
Map<String, Recipient> recipientMap) {
|
Map<String, Recipient> recipientMap) {
|
||||||
|
|
||||||
ContentResolver contentResolver = getContext().getContentResolver();
|
|
||||||
query = "%" + query + "%";
|
query = "%" + query + "%";
|
||||||
|
|
||||||
Uri queryUri = Email.CONTENT_URI;
|
Uri queryUri = Email.CONTENT_URI;
|
||||||
|
@ -391,8 +394,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
|
||||||
Cursor cursor;
|
Cursor cursor;
|
||||||
Uri queryUri = Uri.parse("content://" + cryptoProvider + ".provider.exported/autocrypt_status");
|
Uri queryUri = Uri.parse("content://" + cryptoProvider + ".provider.exported/autocrypt_status");
|
||||||
try {
|
try {
|
||||||
cursor = getContext().getContentResolver().query(queryUri, PROJECTION_CRYPTO_STATUS, null,
|
cursor = contentResolver.query(queryUri, PROJECTION_CRYPTO_STATUS, null, recipientAddresses, null);
|
||||||
recipientAddresses, null);
|
|
||||||
} catch (SecurityException e) {
|
} catch (SecurityException e) {
|
||||||
// TODO escalate error to crypto status?
|
// TODO escalate error to crypto status?
|
||||||
return;
|
return;
|
||||||
|
@ -436,7 +438,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
|
||||||
|
|
||||||
if (observerKey != null) {
|
if (observerKey != null) {
|
||||||
observerKey = new ForceLoadContentObserver();
|
observerKey = new ForceLoadContentObserver();
|
||||||
getContext().getContentResolver().registerContentObserver(queryUri, false, observerKey);
|
contentResolver.registerContentObserver(queryUri, false, observerKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,10 +474,10 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
|
||||||
super.onAbandon();
|
super.onAbandon();
|
||||||
|
|
||||||
if (observerKey != null) {
|
if (observerKey != null) {
|
||||||
getContext().getContentResolver().unregisterContentObserver(observerKey);
|
contentResolver.unregisterContentObserver(observerKey);
|
||||||
}
|
}
|
||||||
if (observerContact != null) {
|
if (observerContact != null) {
|
||||||
getContext().getContentResolver().unregisterContentObserver(observerContact);
|
contentResolver.unregisterContentObserver(observerContact);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,144 @@
|
||||||
|
package com.fsck.k9.activity.compose;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.MatrixCursor;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import com.fsck.k9.K9RobolectricTestRunner;
|
||||||
|
import com.fsck.k9.mail.Address;
|
||||||
|
import com.fsck.k9.view.RecipientSelectView.Recipient;
|
||||||
|
import com.fsck.k9.view.RecipientSelectView.RecipientCryptoStatus;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import static org.mockito.AdditionalMatchers.aryEq;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.eq;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
@RunWith(K9RobolectricTestRunner.class)
|
||||||
|
public class RecipientLoaderTest {
|
||||||
|
static final String CRYPTO_PROVIDER = "cryptoProvider";
|
||||||
|
static final String[] PROJECTION_CRYPTO_ADDRESSES = { "address", "uid_address" };
|
||||||
|
static final String[] PROJECTION_CRYPTO_STATUS = { "address", "uid_key_status", "autocrypt_key_status" };
|
||||||
|
static final Address CONTACT_ADDRESS_1 = Address.parse("Contact Name <address@example.org>")[0];
|
||||||
|
static final Address CONTACT_ADDRESS_2 = Address.parse("Other Contact Name <address_two@example.org>")[0];
|
||||||
|
static final String QUERYSTRING = "querystring";
|
||||||
|
|
||||||
|
|
||||||
|
Context context;
|
||||||
|
ContentResolver contentResolver;
|
||||||
|
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
context = mock(Context.class);
|
||||||
|
contentResolver = mock(ContentResolver.class);
|
||||||
|
|
||||||
|
when(context.getContentResolver()).thenReturn(contentResolver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryCryptoProvider() throws Exception {
|
||||||
|
RecipientLoader recipientLoader = new RecipientLoader(context, CRYPTO_PROVIDER, QUERYSTRING);
|
||||||
|
|
||||||
|
setupQueryCryptoProvider("%" + QUERYSTRING + "%", CONTACT_ADDRESS_1, CONTACT_ADDRESS_2);
|
||||||
|
|
||||||
|
List<Recipient> recipients = recipientLoader.loadInBackground();
|
||||||
|
|
||||||
|
assertEquals(2, recipients.size());
|
||||||
|
assertEquals(CONTACT_ADDRESS_1, recipients.get(0).address);
|
||||||
|
assertEquals(CONTACT_ADDRESS_2, recipients.get(1).address);
|
||||||
|
assertEquals(RecipientCryptoStatus.UNAVAILABLE, recipients.get(0).getCryptoStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryCryptoStatus_unavailable() throws Exception {
|
||||||
|
RecipientLoader recipientLoader = new RecipientLoader(context, CRYPTO_PROVIDER, CONTACT_ADDRESS_1);
|
||||||
|
|
||||||
|
setupCryptoProviderStatus(CONTACT_ADDRESS_1, "0", "0");
|
||||||
|
|
||||||
|
List<Recipient> recipients = recipientLoader.loadInBackground();
|
||||||
|
|
||||||
|
assertEquals(1, recipients.size());
|
||||||
|
Recipient recipient = recipients.get(0);
|
||||||
|
assertEquals(CONTACT_ADDRESS_1, recipient.address);
|
||||||
|
assertEquals(RecipientCryptoStatus.UNAVAILABLE, recipient.getCryptoStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryCryptoStatus_autocrypt_untrusted() throws Exception {
|
||||||
|
RecipientLoader recipientLoader = new RecipientLoader(context, CRYPTO_PROVIDER, CONTACT_ADDRESS_1);
|
||||||
|
|
||||||
|
setupCryptoProviderStatus(CONTACT_ADDRESS_1, "0", "1");
|
||||||
|
|
||||||
|
List<Recipient> recipients = recipientLoader.loadInBackground();
|
||||||
|
|
||||||
|
assertEquals(1, recipients.size());
|
||||||
|
Recipient recipient = recipients.get(0);
|
||||||
|
assertEquals(CONTACT_ADDRESS_1, recipient.address);
|
||||||
|
assertEquals(RecipientCryptoStatus.AVAILABLE_UNTRUSTED, recipient.getCryptoStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryCryptoStatus_autocrypt_trusted() throws Exception {
|
||||||
|
RecipientLoader recipientLoader = new RecipientLoader(context, CRYPTO_PROVIDER, CONTACT_ADDRESS_1);
|
||||||
|
|
||||||
|
setupCryptoProviderStatus(CONTACT_ADDRESS_1, "0", "2");
|
||||||
|
|
||||||
|
List<Recipient> recipients = recipientLoader.loadInBackground();
|
||||||
|
|
||||||
|
assertEquals(1, recipients.size());
|
||||||
|
Recipient recipient = recipients.get(0);
|
||||||
|
assertEquals(CONTACT_ADDRESS_1, recipient.address);
|
||||||
|
assertEquals(RecipientCryptoStatus.AVAILABLE_TRUSTED, recipient.getCryptoStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void queryCryptoStatus_withHigherUidStatus() throws Exception {
|
||||||
|
RecipientLoader recipientLoader = new RecipientLoader(context, CRYPTO_PROVIDER, CONTACT_ADDRESS_1);
|
||||||
|
|
||||||
|
setupCryptoProviderStatus(CONTACT_ADDRESS_1, "2", "1");
|
||||||
|
|
||||||
|
List<Recipient> recipients = recipientLoader.loadInBackground();
|
||||||
|
|
||||||
|
assertEquals(1, recipients.size());
|
||||||
|
Recipient recipient = recipients.get(0);
|
||||||
|
assertEquals(CONTACT_ADDRESS_1, recipient.address);
|
||||||
|
assertEquals(RecipientCryptoStatus.AVAILABLE_TRUSTED, recipient.getCryptoStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupQueryCryptoProvider(String queriedAddress, Address... contactAddresses) {
|
||||||
|
MatrixCursor cursor = new MatrixCursor(PROJECTION_CRYPTO_ADDRESSES);
|
||||||
|
for (Address contactAddress : contactAddresses) {
|
||||||
|
cursor.addRow(new String[] { queriedAddress, contactAddress.toString() });
|
||||||
|
}
|
||||||
|
|
||||||
|
when(contentResolver
|
||||||
|
.query(eq(Uri.parse("content://" + CRYPTO_PROVIDER + ".provider.exported/autocrypt_status")),
|
||||||
|
aryEq(PROJECTION_CRYPTO_ADDRESSES), any(String.class),
|
||||||
|
aryEq(new String[] { queriedAddress }),
|
||||||
|
any(String.class))).thenReturn(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupCryptoProviderStatus(Address address, String uidStatus, String autocryptStatus) {
|
||||||
|
MatrixCursor cursorCryptoStatus = new MatrixCursor(PROJECTION_CRYPTO_STATUS);
|
||||||
|
cursorCryptoStatus.addRow(new String[] { address.getAddress(), uidStatus, autocryptStatus });
|
||||||
|
|
||||||
|
when(contentResolver
|
||||||
|
.query(eq(Uri.parse("content://" + CRYPTO_PROVIDER + ".provider.exported/autocrypt_status")),
|
||||||
|
aryEq(PROJECTION_CRYPTO_STATUS), any(String.class),
|
||||||
|
aryEq(new String[] { address.getAddress() }),
|
||||||
|
any(String.class))).thenReturn(cursorCryptoStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue