1/* 2 * Copyright (C) 2009 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 17package com.android.providers.contacts; 18 19import android.content.ContentUris; 20import android.net.Uri; 21import android.provider.ContactsContract.AggregationExceptions; 22import android.provider.ContactsContract.Contacts; 23import android.provider.ContactsContract.RawContacts; 24import android.test.suitebuilder.annotation.MediumTest; 25 26import com.android.providers.contacts.ContactLookupKey.LookupKeySegment; 27import com.android.providers.contacts.testutil.RawContactUtil; 28 29import java.util.ArrayList; 30 31/** 32 * Unit tests for {@link ContactLookupKey}. 33 * 34 * Run the test like this: 35 * <code> 36 * adb shell am instrument -e class com.android.providers.contacts.ContactLookupKeyTest -w \ 37 * com.android.providers.contacts.tests/android.test.InstrumentationTestRunner 38 * </code> 39 */ 40@MediumTest 41public class ContactLookupKeyTest extends BaseContactsProvider2Test { 42 43 public void testLookupKeyUsingDisplayNameAndNoAccount() { 44 long rawContactId1 = RawContactUtil.createRawContactWithName(mResolver, "John", "Doe"); 45 long rawContactId2 = RawContactUtil.createRawContactWithName(mResolver, "johndoe", null); 46 setAggregationException( 47 AggregationExceptions.TYPE_KEEP_TOGETHER, rawContactId1, rawContactId2); 48 49 // Normalized display name 50 String normalizedName = NameNormalizer.normalize("johndoe"); 51 String expectedLookupKey = "0r" + rawContactId1 + "-" + normalizedName + ".0r" 52 + rawContactId2 + "-" + normalizedName; 53 54 long contactId = queryContactId(rawContactId1); 55 assertStoredValue(ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 56 Contacts.LOOKUP_KEY, expectedLookupKey); 57 58 // Find the contact using lookup key by itself 59 Uri lookupUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, expectedLookupKey); 60 assertStoredValue(lookupUri, Contacts._ID, contactId); 61 62 // Find the contact using both the lookup key and the correct contact ID 63 assertStoredValue(ContentUris.withAppendedId(lookupUri, contactId), 64 Contacts._ID, contactId); 65 66 // Find the contact using both the lookup key and an incorrect contact ID 67 assertStoredValue(ContentUris.withAppendedId(lookupUri, contactId + 1), 68 Contacts._ID, contactId); 69 } 70 71 public void testLookupKeyUsingSourceIdAndNoAccount() { 72 long rawContactId1 = RawContactUtil.createRawContactWithName(mResolver, "John", "Doe"); 73 storeValue(RawContacts.CONTENT_URI, rawContactId1, RawContacts.SOURCE_ID, "123"); 74 75 long rawContactId2 = RawContactUtil.createRawContactWithName(mResolver, "johndoe", null); 76 storeValue(RawContacts.CONTENT_URI, rawContactId2, RawContacts.SOURCE_ID, "4.5.6"); 77 78 long rawContactId3 = RawContactUtil.createRawContactWithName(mResolver, "john", "dough"); 79 storeValue(RawContacts.CONTENT_URI, rawContactId3, RawContacts.SOURCE_ID, "http://foo?bar"); 80 81 setAggregationException( 82 AggregationExceptions.TYPE_KEEP_TOGETHER, rawContactId1, rawContactId2); 83 setAggregationException( 84 AggregationExceptions.TYPE_KEEP_TOGETHER, rawContactId1, rawContactId3); 85 86 // Two source ids, of them escaped 87 String expectedLookupKey = "0i123.0e4..5..6.0ihttp%3A%2F%2Ffoo%3Fbar"; 88 89 long contactId = queryContactId(rawContactId1); 90 assertStoredValue(ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 91 Contacts.LOOKUP_KEY, expectedLookupKey); 92 93 Uri lookupUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, expectedLookupKey); 94 assertStoredValue(lookupUri, Contacts._ID, contactId); 95 } 96 97 public void testLookupKeySameSourceIdDifferentAccounts() { 98 long rawContactId1 = RawContactUtil.createRawContactWithName(mResolver, "Dear", "Doe"); 99 storeValue(RawContacts.CONTENT_URI, rawContactId1, RawContacts.ACCOUNT_TYPE, "foo"); 100 storeValue(RawContacts.CONTENT_URI, rawContactId1, RawContacts.ACCOUNT_NAME, "FOO"); 101 storeValue(RawContacts.CONTENT_URI, rawContactId1, RawContacts.SOURCE_ID, "1"); 102 103 long rawContactId2 = RawContactUtil.createRawContactWithName(mResolver, "Deer", "Dough"); 104 storeValue(RawContacts.CONTENT_URI, rawContactId2, RawContacts.ACCOUNT_TYPE, "bar"); 105 storeValue(RawContacts.CONTENT_URI, rawContactId2, RawContacts.ACCOUNT_NAME, "BAR"); 106 storeValue(RawContacts.CONTENT_URI, rawContactId2, RawContacts.SOURCE_ID, "1"); 107 108 assertNotAggregated(rawContactId1, rawContactId2); 109 110 int accountHashCode1 = ContactLookupKey.getAccountHashCode("foo", "FOO"); 111 int accountHashCode2 = ContactLookupKey.getAccountHashCode("bar", "BAR"); 112 113 long contactId1 = queryContactId(rawContactId1); 114 assertStoredValue(ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId1), 115 Contacts.LOOKUP_KEY, accountHashCode1 + "i1"); 116 117 long contactId2 = queryContactId(rawContactId2); 118 assertStoredValue(ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId2), 119 Contacts.LOOKUP_KEY, accountHashCode2 + "i1"); 120 121 Uri lookupUri1 = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, accountHashCode1 + "i1"); 122 assertStoredValue(lookupUri1, Contacts._ID, contactId1); 123 124 Uri lookupUri2 = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, accountHashCode2 + "i1"); 125 assertStoredValue(lookupUri2, Contacts._ID, contactId2); 126 } 127 128 public void testLookupKeyChoosingLargestContact() { 129 long rawContactId1 = RawContactUtil.createRawContactWithName(mResolver, "John", "Doe"); 130 storeValue(RawContacts.CONTENT_URI, rawContactId1, RawContacts.SOURCE_ID, "1"); 131 132 long rawContactId2 = RawContactUtil.createRawContactWithName(mResolver, "John", "Doe"); 133 storeValue(RawContacts.CONTENT_URI, rawContactId2, RawContacts.SOURCE_ID, "2"); 134 135 long rawContactId3 = RawContactUtil.createRawContactWithName(mResolver, "John", "Doe"); 136 storeValue(RawContacts.CONTENT_URI, rawContactId3, RawContacts.SOURCE_ID, "3"); 137 setAggregationException( 138 AggregationExceptions.TYPE_KEEP_TOGETHER, rawContactId1, rawContactId2); 139 setAggregationException( 140 AggregationExceptions.TYPE_KEEP_TOGETHER, rawContactId1, rawContactId3); 141 142 String lookupKey = "0i1.0i2.0i3"; 143 144 long contactId = queryContactId(rawContactId1); 145 assertStoredValue(ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId), 146 Contacts.LOOKUP_KEY, lookupKey); 147 148 setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE, rawContactId1, 149 rawContactId3); 150 setAggregationException(AggregationExceptions.TYPE_KEEP_SEPARATE, rawContactId2, 151 rawContactId3); 152 assertAggregated(rawContactId1, rawContactId2); 153 assertNotAggregated(rawContactId1, rawContactId3); 154 assertNotAggregated(rawContactId2, rawContactId3); 155 156 long largerContactId = queryContactId(rawContactId1); 157 assertStoredValue( 158 ContentUris.withAppendedId(Contacts.CONTENT_URI, largerContactId), 159 Contacts.LOOKUP_KEY, "0i1.0i2"); 160 assertStoredValue( 161 ContentUris.withAppendedId(Contacts.CONTENT_URI, queryContactId(rawContactId3)), 162 Contacts.LOOKUP_KEY, "0i3"); 163 164 Uri lookupUri = Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, lookupKey); 165 assertStoredValue(lookupUri, Contacts._ID, largerContactId); 166 } 167 168 public void testGetLookupUri() { 169 long rawContactId1 = RawContactUtil.createRawContactWithName(mResolver, "John", "Doe"); 170 storeValue(RawContacts.CONTENT_URI, rawContactId1, RawContacts.SOURCE_ID, "1"); 171 172 long contactId = queryContactId(rawContactId1); 173 String lookupUri = "content://com.android.contacts/contacts/lookup/0i1/" + contactId; 174 175 Uri contentUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId); 176 assertEquals(lookupUri, 177 Contacts.getLookupUri(mResolver, contentUri).toString()); 178 179 Uri staleLookupUri = ContentUris.withAppendedId( 180 Uri.withAppendedPath(Contacts.CONTENT_LOOKUP_URI, "0i1"), 181 contactId+2); 182 assertEquals(lookupUri, 183 Contacts.getLookupUri(mResolver, staleLookupUri).toString()); 184 } 185 186 public void testParseLookupKey() { 187 // Display name 188 assertLookupKey("123n1248AC", 189 new int[]{123}, 190 new int[]{ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME}, 191 new String[]{"1248AC"}); 192 193 // Raw contact ID + display name 194 assertLookupKey("123r20-1248AC", 195 new int[]{123}, 196 new int[]{ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID}, 197 new String[]{"1248AC"}); 198 199 // Unescaped source ID 200 assertLookupKey("0i1248AC-X", 201 new int[]{0}, 202 new int[]{ContactLookupKey.LOOKUP_TYPE_SOURCE_ID}, 203 new String[]{"1248AC-X"}); 204 205 // Escaped source ID 206 assertLookupKey("432e12..48AC", 207 new int[]{432}, 208 new int[]{ContactLookupKey.LOOKUP_TYPE_SOURCE_ID}, 209 new String[]{"12.48AC"}); 210 211 // Compound lookup key 212 assertLookupKey("123n1248AC.0i1248AC.432e12..48AC.123n1248AC.123r30-2184CA", 213 new int[]{123, 0, 432, 123}, 214 new int[] { 215 ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME, 216 ContactLookupKey.LOOKUP_TYPE_SOURCE_ID, 217 ContactLookupKey.LOOKUP_TYPE_SOURCE_ID, 218 ContactLookupKey.LOOKUP_TYPE_DISPLAY_NAME, 219 ContactLookupKey.LOOKUP_TYPE_RAW_CONTACT_ID, 220 }, 221 new String[]{"1248AC", "1248AC", "12.48AC", "1248AC", "2184CA"}); 222 } 223 224 private void assertLookupKey(String lookupKey, int[] accountHashCodes, int[] types, 225 String[] keys) { 226 ContactLookupKey key = new ContactLookupKey(); 227 ArrayList<LookupKeySegment> list = key.parse(lookupKey); 228 assertEquals(types.length, list.size()); 229 230 for (int i = 0; i < accountHashCodes.length; i++) { 231 LookupKeySegment segment = list.get(i); 232 assertEquals(accountHashCodes[i], segment.accountHashCode); 233 assertEquals(types[i], segment.lookupType); 234 assertEquals(keys[i], segment.key); 235 } 236 } 237} 238 239