• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
setUp()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
tearDown()72     protected void tearDown() throws Exception {
73         mMockContext = null;
74         mContactsProvider = null;
75         super.tearDown();
76     }
77 
assertLoadContact(Uri uri)78     private Contact assertLoadContact(Uri uri) {
79         final ContactLoader loader = new ContactLoader(mMockContext, uri, true);
80         return getLoaderResultSynchronously(loader);
81     }
82 
testNullUri()83     public void testNullUri() {
84         Contact result = assertLoadContact(null);
85         assertTrue(result.isError());
86     }
87 
testEmptyUri()88     public void testEmptyUri() {
89         Contact result = assertLoadContact(Uri.EMPTY);
90         assertTrue(result.isError());
91     }
92 
testInvalidUri()93     public void testInvalidUri() {
94         Contact result = assertLoadContact(Uri.parse("content://wtf"));
95         assertTrue(result.isError());
96     }
97 
testLoadContactWithContactIdUri()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 
testLoadContactWithOldStyleUri()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 
testLoadContactWithRawContactIdUri()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 
testLoadContactWithContactLookupUri()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 
testLoadContactWithContactLookupAndIdUri()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 
testLoadContactWithContactLookupWithIncorrectIdUri()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 {
fetchAllData( Uri baseUri, long contactId, long rawContactId, long dataId, String encodedLookup)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 
fetchLookupAndId(final Uri sourceUri, final long expectedContactId, final String expectedEncodedLookup)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 
fetchContactIdAndLookupFromRawContactUri(final Uri rawContactUri, final long expectedContactId, final String expectedEncodedLookup)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