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