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