Home | History | Annotate | Download | only in contacts
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.contacts;
     18 
     19 import com.android.contacts.model.AccountType;
     20 import com.android.contacts.model.AccountWithDataSet;
     21 import com.android.contacts.model.BaseAccountType;
     22 import com.android.contacts.test.InjectedServices;
     23 import com.android.contacts.tests.mocks.ContactsMockContext;
     24 import com.android.contacts.tests.mocks.MockAccountTypeManager;
     25 import com.android.contacts.tests.mocks.MockContentProvider;
     26 
     27 import android.content.ContentUris;
     28 import android.net.Uri;
     29 import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
     30 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
     31 import android.provider.ContactsContract.Contacts;
     32 import android.provider.ContactsContract.Data;
     33 import android.provider.ContactsContract.DisplayNameSources;
     34 import android.provider.ContactsContract.RawContacts;
     35 import android.provider.ContactsContract.StatusUpdates;
     36 import android.test.LoaderTestCase;
     37 import android.test.suitebuilder.annotation.LargeTest;
     38 
     39 /**
     40  * Runs ContactLoader tests for the the contact-detail and editor view.
     41  */
     42 @LargeTest
     43 public class ContactLoaderTest extends LoaderTestCase {
     44     private ContactsMockContext mMockContext;
     45     private MockContentProvider mContactsProvider;
     46 
     47     @Override
     48     protected void setUp() throws Exception {
     49         super.setUp();
     50         mMockContext = new ContactsMockContext(getContext());
     51         mContactsProvider = mMockContext.getContactsProvider();
     52 
     53         InjectedServices services = new InjectedServices();
     54         AccountType accountType = new BaseAccountType() {
     55             @Override
     56             public boolean areContactsWritable() {
     57                 return false;
     58             }
     59         };
     60         accountType.accountType = "mockAccountType";
     61 
     62         AccountWithDataSet account =
     63                 new AccountWithDataSet("mockAccountName", "mockAccountType", null);
     64 
     65         mMockContext.setMockAccountTypeManager(
     66                 new MockAccountTypeManager(
     67                         new AccountType[] { accountType }, new AccountWithDataSet[] { account }));
     68     }
     69 
     70     @Override
     71     protected void tearDown() throws Exception {
     72         mMockContext = null;
     73         mContactsProvider = null;
     74         super.tearDown();
     75     }
     76 
     77     private ContactLoader.Result assertLoadContact(Uri uri) {
     78         final ContactLoader loader = new ContactLoader(mMockContext, uri);
     79         return getLoaderResultSynchronously(loader);
     80     }
     81 
     82     public void testNullUri() {
     83         ContactLoader.Result result = assertLoadContact(null);
     84         assertTrue(result.isError());
     85     }
     86 
     87     public void testEmptyUri() {
     88         ContactLoader.Result result = assertLoadContact(Uri.EMPTY);
     89         assertTrue(result.isError());
     90     }
     91 
     92     public void testInvalidUri() {
     93         ContactLoader.Result result = assertLoadContact(Uri.parse("content://wtf"));
     94         assertTrue(result.isError());
     95     }
     96 
     97     public void testLoadContactWithContactIdUri() {
     98         // Use content Uris that only contain the ID
     99         final long contactId = 1;
    100         final long rawContactId = 11;
    101         final long dataId = 21;
    102 
    103         final String lookupKey = "aa%12%@!";
    104         final Uri baseUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
    105         final Uri entityUri = Uri.withAppendedPath(baseUri, Contacts.Entity.CONTENT_DIRECTORY);
    106         final Uri lookupUri = ContentUris.withAppendedId(
    107                 Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey),
    108                 contactId);
    109 
    110         ContactQueries queries = new ContactQueries();
    111         mContactsProvider.expectTypeQuery(baseUri, Contacts.CONTENT_ITEM_TYPE);
    112         queries.fetchAllData(entityUri, contactId, rawContactId, dataId, lookupKey);
    113 
    114         ContactLoader.Result contact = assertLoadContact(baseUri);
    115 
    116         assertEquals(contactId, contact.getId());
    117         assertEquals(rawContactId, contact.getNameRawContactId());
    118         assertEquals(DisplayNameSources.STRUCTURED_NAME, contact.getDisplayNameSource());
    119         assertEquals(lookupKey, contact.getLookupKey());
    120         assertEquals(lookupUri, contact.getLookupUri());
    121         assertEquals(1, contact.getEntities().size());
    122         assertEquals(1, contact.getStatuses().size());
    123         mContactsProvider.verify();
    124     }
    125 
    126     public void testLoadContactWithOldStyleUri() {
    127         // Use content Uris that only contain the ID but use the format used in Donut
    128         final long contactId = 1;
    129         final long rawContactId = 11;
    130         final long dataId = 21;
    131 
    132         final String lookupKey = "aa%12%@!";
    133         final Uri legacyUri = ContentUris.withAppendedId(
    134                 Uri.parse("content://contacts"), rawContactId);
    135         final Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
    136         final Uri baseUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
    137         final Uri lookupUri = ContentUris.withAppendedId(
    138                 Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey),
    139                 contactId);
    140         final Uri entityUri = Uri.withAppendedPath(lookupUri, Contacts.Entity.CONTENT_DIRECTORY);
    141 
    142         ContactQueries queries = new ContactQueries();
    143         queries.fetchContactIdAndLookupFromRawContactUri(rawContactUri, contactId, lookupKey);
    144         queries.fetchAllData(entityUri, contactId, rawContactId, dataId, lookupKey);
    145 
    146         ContactLoader.Result contact = assertLoadContact(legacyUri);
    147 
    148         assertEquals(contactId, contact.getId());
    149         assertEquals(rawContactId, contact.getNameRawContactId());
    150         assertEquals(DisplayNameSources.STRUCTURED_NAME, contact.getDisplayNameSource());
    151         assertEquals(lookupKey, contact.getLookupKey());
    152         assertEquals(lookupUri, contact.getLookupUri());
    153         assertEquals(1, contact.getEntities().size());
    154         assertEquals(1, contact.getStatuses().size());
    155         mContactsProvider.verify();
    156     }
    157 
    158     public void testLoadContactWithRawContactIdUri() {
    159         // Use content Uris that only contain the ID but use the format used in Donut
    160         final long contactId = 1;
    161         final long rawContactId = 11;
    162         final long dataId = 21;
    163 
    164         final String lookupKey = "aa%12%@!";
    165         final Uri rawContactUri = ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId);
    166         final Uri baseUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
    167         final Uri lookupUri = ContentUris.withAppendedId(
    168                 Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey),
    169                 contactId);
    170         final Uri entityUri = Uri.withAppendedPath(lookupUri, Contacts.Entity.CONTENT_DIRECTORY);
    171 
    172         ContactQueries queries = new ContactQueries();
    173         mContactsProvider.expectTypeQuery(rawContactUri, RawContacts.CONTENT_ITEM_TYPE);
    174         queries.fetchContactIdAndLookupFromRawContactUri(rawContactUri, contactId, lookupKey);
    175         queries.fetchAllData(entityUri, contactId, rawContactId, dataId, lookupKey);
    176 
    177         ContactLoader.Result contact = assertLoadContact(rawContactUri);
    178 
    179         assertEquals(contactId, contact.getId());
    180         assertEquals(rawContactId, contact.getNameRawContactId());
    181         assertEquals(DisplayNameSources.STRUCTURED_NAME, contact.getDisplayNameSource());
    182         assertEquals(lookupKey, contact.getLookupKey());
    183         assertEquals(lookupUri, contact.getLookupUri());
    184         assertEquals(1, contact.getEntities().size());
    185         assertEquals(1, contact.getStatuses().size());
    186         mContactsProvider.verify();
    187     }
    188 
    189     public void testLoadContactWithContactLookupUri() {
    190         // Use lookup-style Uris that do not contain the Contact-ID
    191 
    192         final long contactId = 1;
    193         final long rawContactId = 11;
    194         final long dataId = 21;
    195 
    196         final String lookupKey = "aa%12%@!";
    197         final Uri baseUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
    198         final Uri lookupNoIdUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey);
    199         final Uri lookupUri = ContentUris.withAppendedId(lookupNoIdUri, contactId);
    200         final Uri entityUri = Uri.withAppendedPath(lookupNoIdUri, Contacts.Entity.CONTENT_DIRECTORY);
    201 
    202         ContactQueries queries = new ContactQueries();
    203         mContactsProvider.expectTypeQuery(lookupNoIdUri, Contacts.CONTENT_ITEM_TYPE);
    204         queries.fetchAllData(entityUri, contactId, rawContactId, dataId, lookupKey);
    205 
    206         ContactLoader.Result contact = assertLoadContact(lookupNoIdUri);
    207 
    208         assertEquals(contactId, contact.getId());
    209         assertEquals(rawContactId, contact.getNameRawContactId());
    210         assertEquals(DisplayNameSources.STRUCTURED_NAME, contact.getDisplayNameSource());
    211         assertEquals(lookupKey, contact.getLookupKey());
    212         assertEquals(lookupUri, contact.getLookupUri());
    213         assertEquals(1, contact.getEntities().size());
    214         assertEquals(1, contact.getStatuses().size());
    215         mContactsProvider.verify();
    216     }
    217 
    218     public void testLoadContactWithContactLookupAndIdUri() {
    219         // Use lookup-style Uris that also contain the Contact-ID
    220         final long contactId = 1;
    221         final long rawContactId = 11;
    222         final long dataId = 21;
    223 
    224         final String lookupKey = "aa%12%@!";
    225         final Uri baseUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
    226         final Uri lookupUri = ContentUris.withAppendedId(
    227                 Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey),
    228                 contactId);
    229         final Uri entityUri = Uri.withAppendedPath(lookupUri, Contacts.Entity.CONTENT_DIRECTORY);
    230 
    231         ContactQueries queries = new ContactQueries();
    232         mContactsProvider.expectTypeQuery(lookupUri, Contacts.CONTENT_ITEM_TYPE);
    233         queries.fetchAllData(entityUri, contactId, rawContactId, dataId, lookupKey);
    234 
    235         ContactLoader.Result contact = assertLoadContact(lookupUri);
    236 
    237         assertEquals(contactId, contact.getId());
    238         assertEquals(rawContactId, contact.getNameRawContactId());
    239         assertEquals(DisplayNameSources.STRUCTURED_NAME, contact.getDisplayNameSource());
    240         assertEquals(lookupKey, contact.getLookupKey());
    241         assertEquals(lookupUri, contact.getLookupUri());
    242         assertEquals(1, contact.getEntities().size());
    243         assertEquals(1, contact.getStatuses().size());
    244         mContactsProvider.verify();
    245     }
    246 
    247     public void testLoadContactWithContactLookupWithIncorrectIdUri() {
    248         // Use lookup-style Uris that contain incorrect Contact-ID
    249         // (we want to ensure that still the correct contact is chosen)
    250 
    251         final long contactId = 1;
    252         final long wrongContactId = 2;
    253         final long rawContactId = 11;
    254         final long wrongRawContactId = 12;
    255         final long dataId = 21;
    256 
    257         final String lookupKey = "aa%12%@!";
    258         final String wrongLookupKey = "ab%12%@!";
    259         final Uri baseUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
    260         final Uri wrongBaseUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, wrongContactId);
    261         final Uri lookupUri = ContentUris.withAppendedId(
    262                 Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey),
    263                 contactId);
    264         final Uri lookupWithWrongIdUri = ContentUris.withAppendedId(
    265                 Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey),
    266                 wrongContactId);
    267         final Uri entityUri = Uri.withAppendedPath(lookupWithWrongIdUri,
    268                 Contacts.Entity.CONTENT_DIRECTORY);
    269 
    270         ContactQueries queries = new ContactQueries();
    271         mContactsProvider.expectTypeQuery(lookupWithWrongIdUri, Contacts.CONTENT_ITEM_TYPE);
    272         queries.fetchAllData(entityUri, contactId, rawContactId, dataId, lookupKey);
    273 
    274         ContactLoader.Result contact = assertLoadContact(lookupWithWrongIdUri);
    275 
    276         assertEquals(contactId, contact.getId());
    277         assertEquals(rawContactId, contact.getNameRawContactId());
    278         assertEquals(DisplayNameSources.STRUCTURED_NAME, contact.getDisplayNameSource());
    279         assertEquals(lookupKey, contact.getLookupKey());
    280         assertEquals(lookupUri, contact.getLookupUri());
    281         assertEquals(1, contact.getEntities().size());
    282         assertEquals(1, contact.getStatuses().size());
    283 
    284         mContactsProvider.verify();
    285     }
    286 
    287     class ContactQueries {
    288         public void fetchAllData(
    289                 Uri baseUri, long contactId, long rawContactId, long dataId, String encodedLookup) {
    290             mContactsProvider.expectQuery(baseUri)
    291                     .withProjection(new String[] {
    292                         Contacts.NAME_RAW_CONTACT_ID, Contacts.DISPLAY_NAME_SOURCE,
    293                         Contacts.LOOKUP_KEY, Contacts.DISPLAY_NAME,
    294                         Contacts.DISPLAY_NAME_ALTERNATIVE, Contacts.PHONETIC_NAME,
    295                         Contacts.PHOTO_ID, Contacts.STARRED, Contacts.CONTACT_PRESENCE,
    296                         Contacts.CONTACT_STATUS, Contacts.CONTACT_STATUS_TIMESTAMP,
    297                         Contacts.CONTACT_STATUS_RES_PACKAGE, Contacts.CONTACT_STATUS_LABEL,
    298 
    299                         Contacts.Entity.CONTACT_ID,
    300                         Contacts.Entity.RAW_CONTACT_ID,
    301 
    302                         RawContacts.ACCOUNT_NAME, RawContacts.ACCOUNT_TYPE,
    303                         RawContacts.DATA_SET, RawContacts.ACCOUNT_TYPE_AND_DATA_SET,
    304                         RawContacts.DIRTY, RawContacts.VERSION, RawContacts.SOURCE_ID,
    305                         RawContacts.SYNC1, RawContacts.SYNC2, RawContacts.SYNC3, RawContacts.SYNC4,
    306                         RawContacts.DELETED, RawContacts.NAME_VERIFIED,
    307 
    308                         Contacts.Entity.DATA_ID,
    309 
    310                         Data.DATA1, Data.DATA2, Data.DATA3, Data.DATA4, Data.DATA5,
    311                         Data.DATA6, Data.DATA7, Data.DATA8, Data.DATA9, Data.DATA10,
    312                         Data.DATA11, Data.DATA12, Data.DATA13, Data.DATA14, Data.DATA15,
    313                         Data.SYNC1, Data.SYNC2, Data.SYNC3, Data.SYNC4,
    314                         Data.DATA_VERSION, Data.IS_PRIMARY,
    315                         Data.IS_SUPER_PRIMARY, Data.MIMETYPE, Data.RES_PACKAGE,
    316 
    317                         GroupMembership.GROUP_SOURCE_ID,
    318 
    319                         Data.PRESENCE, Data.CHAT_CAPABILITY,
    320                         Data.STATUS, Data.STATUS_RES_PACKAGE, Data.STATUS_ICON,
    321                         Data.STATUS_LABEL, Data.STATUS_TIMESTAMP,
    322 
    323                         Contacts.PHOTO_URI,
    324 
    325                         Contacts.SEND_TO_VOICEMAIL,
    326                         Contacts.CUSTOM_RINGTONE,
    327                         Contacts.IS_USER_PROFILE,
    328                     })
    329                     .withSortOrder(Contacts.Entity.RAW_CONTACT_ID)
    330                     .returnRow(
    331                         rawContactId, 40,
    332                         "aa%12%@!", "John Doe", "Doe, John", "jdo",
    333                         0, 0, StatusUpdates.AVAILABLE,
    334                         "Having lunch", 0,
    335                         "mockPkg1", 10,
    336 
    337                         contactId,
    338                         rawContactId,
    339 
    340                         "mockAccountName", "mockAccountType", null, "mockAccountType",
    341                         0, 1, 0,
    342                         "sync1", "sync2", "sync3", "sync4",
    343                         0, 0,
    344 
    345                         dataId,
    346 
    347                         "dat1", "dat2", "dat3", "dat4", "dat5",
    348                         "dat6", "dat7", "dat8", "dat9", "dat10",
    349                         "dat11", "dat12", "dat13", "dat14", "dat15",
    350                         "syn1", "syn2", "syn3", "syn4",
    351 
    352                         0, 0,
    353                         0, StructuredName.CONTENT_ITEM_TYPE, "mockPkg2",
    354 
    355                         "groupId",
    356 
    357                         StatusUpdates.INVISIBLE, null,
    358                         "Having dinner", "mockPkg3", 0,
    359                         20, 0,
    360 
    361                         "content:some.photo.uri",
    362 
    363                         0,
    364                         null,
    365                         0
    366                     );
    367         }
    368 
    369         void fetchLookupAndId(final Uri sourceUri, final long expectedContactId,
    370                 final String expectedEncodedLookup) {
    371             mContactsProvider.expectQuery(sourceUri)
    372                     .withProjection(Contacts.LOOKUP_KEY, Contacts._ID)
    373                     .returnRow(expectedEncodedLookup, expectedContactId);
    374         }
    375 
    376         void fetchContactIdAndLookupFromRawContactUri(final Uri rawContactUri,
    377                 final long expectedContactId, final String expectedEncodedLookup) {
    378             // TODO: use a lighter query by joining rawcontacts with contacts in provider
    379             // (See ContactContracts.java)
    380             final Uri dataUri = Uri.withAppendedPath(rawContactUri,
    381                     RawContacts.Data.CONTENT_DIRECTORY);
    382             mContactsProvider.expectQuery(dataUri)
    383                     .withProjection(RawContacts.CONTACT_ID, Contacts.LOOKUP_KEY)
    384                     .returnRow(expectedContactId, expectedEncodedLookup);
    385         }
    386     }
    387 }
    388