Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c2171b51 authored by Vincent Breitmoser's avatar Vincent Breitmoser
Browse files

add some unit tests for RecipientLoader

parent fca46301
Loading
Loading
Loading
Loading
+17 −15
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
    private final Uri contactUri;
    private final Uri lookupKeyUri;
    private final String cryptoProvider;
    private final ContentResolver contentResolver;

    private List<Recipient> cachedRecipients;
    private ForceLoadContentObserver observerContact, observerKey;
@@ -97,6 +98,8 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
        this.addresses = null;
        this.contactUri = null;
        this.cryptoProvider = cryptoProvider;

        contentResolver = context.getContentResolver();
    }

    public RecipientLoader(Context context, String cryptoProvider, Address... addresses) {
@@ -106,6 +109,8 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
        this.contactUri = null;
        this.cryptoProvider = cryptoProvider;
        this.lookupKeyUri = null;

        contentResolver = context.getContentResolver();
    }

    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.lookupKeyUri = isLookupKey ? contactUri : null;
        this.cryptoProvider = cryptoProvider;

        contentResolver = context.getContentResolver();
    }

    @Override
@@ -154,7 +161,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
        Cursor cursor;
        try {
            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);

            if (cursor == null) {
@@ -195,7 +202,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {

    private void fillContactDataFromEmailContentUri(Uri contactUri, List<Recipient> recipients,
            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) {
            return;
@@ -207,14 +214,14 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
    private void fillContactDataFromLookupKey(Uri lookupKeyUri, List<Recipient> recipients,
            Map<String, Recipient> recipientMap) {
        // 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) {
            return;
        }

        String contactIdStr = getContactIdFromContactUri(contactContentUri);

        Cursor cursor = getContext().getContentResolver().query(
        Cursor cursor = contentResolver.query(
                ContactsContract.CommonDataKinds.Email.CONTENT_URI,
                PROJECTION, ContactsContract.CommonDataKinds.Email.CONTACT_ID + "=?",
                new String[] { contactIdStr }, null);
@@ -236,7 +243,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {

        Uri queryUriForNickname = ContactsContract.Data.CONTENT_URI;

        return getContext().getContentResolver().query(queryUriForNickname,
        return contentResolver.query(queryUriForNickname,
                PROJECTION_NICKNAME,
                ContactsContract.CommonDataKinds.Nickname.NAME + " LIKE ? AND " +
                        Data.MIMETYPE + " = ?",
@@ -261,7 +268,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
    private void registerContentObserver() {
        if (observerContact != null) {
            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;

        final ContentResolver contentResolver = getContext().getContentResolver();

        Uri queryUri = Email.CONTENT_URI;

        Cursor nicknameCursor = getNicknameCursor(nickname);
@@ -303,8 +308,6 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {

    private boolean fillContactDataFromNameAndEmail(String query, List<Recipient> recipients,
            Map<String, Recipient> recipientMap) {

        ContentResolver contentResolver = getContext().getContentResolver();
        query = "%" + query + "%";

        Uri queryUri = Email.CONTENT_URI;
@@ -391,8 +394,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
        Cursor cursor;
        Uri queryUri = Uri.parse("content://" + cryptoProvider + ".provider.exported/autocrypt_status");
        try {
            cursor = getContext().getContentResolver().query(queryUri, PROJECTION_CRYPTO_STATUS, null,
                    recipientAddresses, null);
            cursor = contentResolver.query(queryUri, PROJECTION_CRYPTO_STATUS, null, recipientAddresses, null);
        } catch (SecurityException e) {
            // TODO escalate error to crypto status?
            return;
@@ -436,7 +438,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {

        if (observerKey != null) {
            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();

        if (observerKey != null) {
            getContext().getContentResolver().unregisterContentObserver(observerKey);
            contentResolver.unregisterContentObserver(observerKey);
        }
        if (observerContact != null) {
            getContext().getContentResolver().unregisterContentObserver(observerContact);
            contentResolver.unregisterContentObserver(observerContact);
        }
    }
}
+144 −0
Original line number Diff line number Diff line
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);
    }

}
 No newline at end of file