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.ContentValues;
20import android.net.Uri;
21import android.net.Uri.Builder;
22import android.provider.ContactsContract.CommonDataKinds.Im;
23import android.provider.ContactsContract.CommonDataKinds.Organization;
24import android.provider.ContactsContract.CommonDataKinds.StructuredName;
25import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
26import android.provider.ContactsContract.Contacts;
27import android.provider.ContactsContract.SearchSnippetColumns;
28import android.test.suitebuilder.annotation.MediumTest;
29import android.test.suitebuilder.annotation.Suppress;
30
31import java.text.Collator;
32import java.util.Arrays;
33import java.util.Locale;
34
35/**
36 * Unit tests for {@link SearchIndexManager}.
37 *
38 * Run the test like this:
39 * <code>
40 * adb shell am instrument -e class com.android.providers.contacts.SearchIndexManagerTest -w \
41 *         com.android.providers.contacts.tests/android.test.InstrumentationTestRunner
42 * </code>
43 */
44@MediumTest
45public class SearchIndexManagerTest extends BaseContactsProvider2Test {
46
47    public void testSearchIndexForStructuredName() {
48        long rawContactId = createRawContact();
49        long contactId = queryContactId(rawContactId);
50        insertStructuredName(rawContactId, "John", "Doe");
51        ContentValues values = new ContentValues();
52        values.put(StructuredName.DISPLAY_NAME, "Bob I. Parr");
53        insertStructuredName(rawContactId, values);
54        values.clear();
55        values.put(StructuredName.PREFIX, "Mrs.");
56        values.put(StructuredName.GIVEN_NAME, "Helen");
57        values.put(StructuredName.MIDDLE_NAME, "I.");
58        values.put(StructuredName.FAMILY_NAME, "Parr");
59        values.put(StructuredName.SUFFIX, "PhD");
60        values.put(StructuredName.PHONETIC_FAMILY_NAME, "par");
61        values.put(StructuredName.PHONETIC_GIVEN_NAME, "helen");
62        insertStructuredName(rawContactId, values);
63
64        assertSearchIndex(
65                contactId, null, "John Doe Bob I Parr Helen I Parr PhD par helen parhelen", null);
66    }
67
68    public void testSearchIndexForChineseName() {
69        // Only run this test when Chinese collation is supported
70        if (!Arrays.asList(Collator.getAvailableLocales()).contains(Locale.CHINA)) {
71            return;
72        }
73
74        long rawContactId = createRawContact();
75        long contactId = queryContactId(rawContactId);
76        ContentValues values = new ContentValues();
77        values.put(StructuredName.DISPLAY_NAME, "\u695A\u8FAD");    // CHUCI
78        insertStructuredName(rawContactId, values);
79
80        assertSearchIndex(
81                contactId, null, "\u695A\u8FAD \u695A\u8FAD CI \u8FAD CHUCI CC C", null);
82    }
83
84    public void testSearchByChineseName() {
85        // Only run this test when Chinese collation is supported
86        if (!Arrays.asList(Collator.getAvailableLocales()).contains(Locale.CHINA)) {
87            return;
88        }
89
90        long rawContactId = createRawContact();
91        ContentValues values = new ContentValues();
92        values.put(StructuredName.DISPLAY_NAME, "\u695A\u8FAD");    // CHUCI
93        insertStructuredName(rawContactId, values);
94
95        assertStoredValue(buildSearchUri("\u695A\u8FAD"), SearchSnippetColumns.SNIPPET, null);
96        assertStoredValue(buildSearchUri("\u8FAD"), SearchSnippetColumns.SNIPPET, null);
97        assertStoredValue(buildSearchUri("CI"), SearchSnippetColumns.SNIPPET, null);
98        assertStoredValue(buildSearchUri("CHUCI"), SearchSnippetColumns.SNIPPET, null);
99        assertStoredValue(buildSearchUri("CC"), SearchSnippetColumns.SNIPPET, null);
100        assertStoredValue(buildSearchUri("C"), SearchSnippetColumns.SNIPPET, null);
101    }
102
103    public void testSearchIndexForKoreanName() {
104        // Only run this test when Korean collation is supported
105        if (!Arrays.asList(Collator.getAvailableLocales()).contains(Locale.KOREA)) {
106            return;
107        }
108
109        long rawContactId = createRawContact();
110        long contactId = queryContactId(rawContactId);
111        ContentValues values = new ContentValues();
112        values.put(StructuredName.DISPLAY_NAME, "\uC774\uC0C1\uC77C");    // Lee Sang Il
113        insertStructuredName(rawContactId, values);
114
115        assertSearchIndex(contactId, null,
116                "\uC774\uC0C1\uC77C \uC0C1\uC77C \u1109\u110B \u110B\u1109\u110B", null);
117    }
118
119    public void testSearchByKoreanName() {
120        // Only run this test when Korean collation is supported
121        if (!Arrays.asList(Collator.getAvailableLocales()).contains(Locale.KOREA)) {
122            return;
123        }
124
125        long rawContactId = createRawContact();
126        ContentValues values = new ContentValues();
127        values.put(StructuredName.DISPLAY_NAME, "\uC774\uC0C1\uC77C");   // Lee Sang Il
128        insertStructuredName(rawContactId, values);
129
130        // Full name: Lee Sang Il
131        assertStoredValue(buildSearchUri("\uC774\uC0C1\uC77C"), SearchSnippetColumns.SNIPPET, null);
132
133        // Given name: Sang Il
134        assertStoredValue(buildSearchUri("\uC0C1\uC77C"), SearchSnippetColumns.SNIPPET, null);
135
136        // Consonants of given name: SIOS IEUNG
137        assertStoredValue(buildSearchUri("\u1109\u110B"), SearchSnippetColumns.SNIPPET, null);
138
139        // Consonants of full name: RIEUL SIOS IEUNG
140        assertStoredValue(buildSearchUri("\u110B\u1109\u110B"), SearchSnippetColumns.SNIPPET, null);
141    }
142
143    public void testSearchByKoreanNameWithTwoCharactersFamilyName() {
144        // Only run this test when Korean collation is supported.
145        if (!Arrays.asList(Collator.getAvailableLocales()).contains(Locale.KOREA)) {
146            return;
147        }
148
149        long rawContactId = createRawContact();
150
151        // Sun Woo Young Nyeu
152        ContentValues values = new ContentValues();
153        values.put(StructuredName.DISPLAY_NAME, "\uC120\uC6B0\uC6A9\uB140");
154
155        insertStructuredName(rawContactId, values);
156
157        // Full name: Sun Woo Young Nyeu
158        assertStoredValue(
159                buildSearchUri("\uC120\uC6B0\uC6A9\uB140"), SearchSnippetColumns.SNIPPET, null);
160
161        // Given name: Young Nyeu
162        assertStoredValue(buildSearchUri("\uC6A9\uB140"), SearchSnippetColumns.SNIPPET, null);
163
164        // Consonants of given name: IEUNG NIEUN
165        assertStoredValue(buildSearchUri("\u110B\u1102"), SearchSnippetColumns.SNIPPET, null);
166
167        // Consonants of full name: SIOS IEUNG IEUNG NIEUN
168        assertStoredValue(
169                buildSearchUri("\u1109\u110B\u110B\u1102"), SearchSnippetColumns.SNIPPET, null);
170    }
171
172    public void testSearchIndexForOrganization() {
173        long rawContactId = createRawContact();
174        long contactId = queryContactId(rawContactId);
175        ContentValues values = new ContentValues();
176        values.put(Organization.COMPANY, "Acme Inc.");
177        values.put(Organization.TITLE, "Director");
178        values.put(Organization.DEPARTMENT, "Phones and tablets");
179        values.put(Organization.JOB_DESCRIPTION, "full text search");
180        values.put(Organization.SYMBOL, "ACME");
181        values.put(Organization.PHONETIC_NAME, "ack-me");
182        values.put(Organization.OFFICE_LOCATION, "virtual");
183        insertOrganization(rawContactId, values);
184
185        assertSearchIndex(contactId,
186                "Director, Acme Inc. (ack-me) (ACME)/Phones and tablets/virtual/full text search",
187                null, null);
188    }
189
190    public void testSearchIndexForPhoneNumber() {
191        long rawContactId = createRawContact();
192        long contactId = queryContactId(rawContactId);
193        insertPhoneNumber(rawContactId, "800555GOOG");
194        insertPhoneNumber(rawContactId, "8005551234");
195
196        assertSearchIndex(contactId, null, null, "8005554664 +18005554664 8005551234 +18005551234");
197    }
198
199    public void testSearchIndexForEmail() {
200        long rawContactId = createRawContact();
201        long contactId = queryContactId(rawContactId);
202        insertEmail(rawContactId, "Bob Parr <incredible@android.com>");
203        insertEmail(rawContactId, "bob_parr@android.com");
204
205        assertSearchIndex(contactId, "Bob Parr <incredible@android.com>\nbob_parr@android.com",
206                null, null);
207    }
208
209    public void testSearchIndexForNickname() {
210        long rawContactId = createRawContact();
211        long contactId = queryContactId(rawContactId);
212        insertNickname(rawContactId, "incredible");
213
214        assertSearchIndex(contactId, "incredible", null, null);
215    }
216
217    public void testSearchIndexForStructuredPostal() {
218        long rawContactId = createRawContact();
219        long contactId = queryContactId(rawContactId);
220        insertPostalAddress(rawContactId, "1600 Amphitheatre Pkwy\nMountain View, CA 94043");
221        ContentValues values = new ContentValues();
222        values.put(StructuredPostal.CITY, "London");
223        values.put(StructuredPostal.STREET, "76 Buckingham Palace Road");
224        values.put(StructuredPostal.POSTCODE, "SW1W 9TQ");
225        values.put(StructuredPostal.COUNTRY, "United Kingdom");
226        insertPostalAddress(rawContactId, values);
227
228        assertSearchIndex(contactId, "1600 Amphitheatre Pkwy Mountain View, CA 94043\n"
229                + "76 Buckingham Palace Road London SW1W 9TQ United Kingdom", null, null);
230    }
231
232    public void testSearchIndexForIm() {
233        long rawContactId = createRawContact();
234        long contactId = queryContactId(rawContactId);
235        insertImHandle(rawContactId, Im.PROTOCOL_JABBER, null, "bp@android.com");
236        insertImHandle(rawContactId, Im.PROTOCOL_CUSTOM, "android_im", "android@android.com");
237
238        assertSearchIndex(
239                contactId, "Jabber/bp@android.com\nandroid_im/android@android.com", null, null);
240    }
241
242    public void testSearchIndexForNote() {
243        long rawContactId = createRawContact();
244        long contactId = queryContactId(rawContactId);
245        insertNote(rawContactId, "Please note: three notes or more make up a chord.");
246
247        assertSearchIndex(
248                contactId, "Please note: three notes or more make up a chord.", null, null);
249    }
250
251    public void testSnippetArgs() {
252        long rawContactId = createRawContact();
253        insertNote(rawContactId, "Please note: three notes or more make up a chord.");
254
255        assertStoredValue(
256                buildSearchUri("thr", "[,],-,2", false), SearchSnippetColumns.SNIPPET,
257                "-note: [three]-");
258    }
259
260    public void testEmptyFilter() {
261        createRawContactWithName("John", "Doe");
262        assertEquals(0, getCount(buildSearchUri(""), null, null));
263    }
264
265    public void testSearchByName() {
266        createRawContactWithName("John Jay", "Doe");
267
268        // We are supposed to find the contact, but return a null snippet
269        assertStoredValue(buildSearchUri("john"), SearchSnippetColumns.SNIPPET, null);
270        assertStoredValue(buildSearchUri("jay"), SearchSnippetColumns.SNIPPET, null);
271        assertStoredValue(buildSearchUri("doe"), SearchSnippetColumns.SNIPPET, null);
272    }
273
274    public void testSearchByPrefixName() {
275        createRawContactWithName("John Jay", "Doe");
276
277        // prefix searches
278        assertStoredValue(buildSearchUri("jo ja"), SearchSnippetColumns.SNIPPET, null);
279        assertStoredValue(buildSearchUri("J D"), SearchSnippetColumns.SNIPPET, null);
280        assertStoredValue(buildSearchUri("Doe, John"), SearchSnippetColumns.SNIPPET, null);
281    }
282
283    public void testGermanUmlautFullameCapitalizationSearch() {
284        createRawContactWithName("Matthäus BJÃRN Bünyamin", "ReiÃer");
285
286        // make sure we can find those, independent of the capitalization
287        assertStoredValue(buildSearchUri("matthäus"), SearchSnippetColumns.SNIPPET, null);
288        assertStoredValue(buildSearchUri("Matthäus"), SearchSnippetColumns.SNIPPET, null);
289        assertStoredValue(buildSearchUri("MATTHÃUS"), SearchSnippetColumns.SNIPPET, null);
290
291        assertStoredValue(buildSearchUri("björn"), SearchSnippetColumns.SNIPPET, null);
292        assertStoredValue(buildSearchUri("Björn"), SearchSnippetColumns.SNIPPET, null);
293        assertStoredValue(buildSearchUri("BJÃRN"), SearchSnippetColumns.SNIPPET, null);
294
295        assertStoredValue(buildSearchUri("bünyamin"), SearchSnippetColumns.SNIPPET, null);
296        assertStoredValue(buildSearchUri("Bünyamin"), SearchSnippetColumns.SNIPPET, null);
297        assertStoredValue(buildSearchUri("BUNYAMIN"), SearchSnippetColumns.SNIPPET, null);
298
299        // There is no capital version of Ã. It is capitalized as double-S instead
300        assertStoredValue(buildSearchUri("ReiÃer"), SearchSnippetColumns.SNIPPET, null);
301        assertStoredValue(buildSearchUri("Reisser"), SearchSnippetColumns.SNIPPET, null);
302        assertStoredValue(buildSearchUri("REISSER"), SearchSnippetColumns.SNIPPET, null);
303    }
304
305    public void testHangulNameLeadConsonantAsYouTypeSearch() {
306        createRawContactWithDisplayName("í길ë");
307        // the korean name uses three compound characters. this test makes sure
308        // that the name can be found by typing in only the lead consonant
309        assertStoredValue(buildSearchUri("ã"), SearchSnippetColumns.SNIPPET, null);
310        assertStoredValue(buildSearchUri("ãã±"), SearchSnippetColumns.SNIPPET, null);
311        assertStoredValue(buildSearchUri("ãã±ã·"), SearchSnippetColumns.SNIPPET, null);
312
313        // same again, this time only for the first name
314        assertStoredValue(buildSearchUri("ã±"), SearchSnippetColumns.SNIPPET, null);
315        assertStoredValue(buildSearchUri("ã±ã·"), SearchSnippetColumns.SNIPPET, null);
316    }
317
318    public void testHangulNameFullAsYouTypeSearch() {
319        createRawContactWithDisplayName("í길ë");
320
321        // the korean name uses three compound characters. this test makes sure
322        // that the name can be found by typing in the full nine letters. the search string
323        // shows the name is being built "as you type"
324        assertStoredValue(buildSearchUri("ã"), SearchSnippetColumns.SNIPPET, null);
325        assertStoredValue(buildSearchUri("í¸"), SearchSnippetColumns.SNIPPET, null);
326        assertStoredValue(buildSearchUri("í"), SearchSnippetColumns.SNIPPET, null);
327        assertStoredValue(buildSearchUri("íã±"), SearchSnippetColumns.SNIPPET, null);
328        assertStoredValue(buildSearchUri("í기"), SearchSnippetColumns.SNIPPET, null);
329        assertStoredValue(buildSearchUri("í길"), SearchSnippetColumns.SNIPPET, null);
330        assertStoredValue(buildSearchUri("í길ã·"), SearchSnippetColumns.SNIPPET, null);
331        assertStoredValue(buildSearchUri("í길ë"), SearchSnippetColumns.SNIPPET, null);
332        assertStoredValue(buildSearchUri("í길ë"), SearchSnippetColumns.SNIPPET, null);
333
334        // same again, this time only for the first name
335        assertStoredValue(buildSearchUri("ã±"), SearchSnippetColumns.SNIPPET, null);
336        assertStoredValue(buildSearchUri("기"), SearchSnippetColumns.SNIPPET, null);
337        assertStoredValue(buildSearchUri("길"), SearchSnippetColumns.SNIPPET, null);
338        assertStoredValue(buildSearchUri("길ã·"), SearchSnippetColumns.SNIPPET, null);
339        assertStoredValue(buildSearchUri("길ë"), SearchSnippetColumns.SNIPPET, null);
340        assertStoredValue(buildSearchUri("길ë"), SearchSnippetColumns.SNIPPET, null);
341    }
342
343
344    /** Decomposed Hangul is not yet supported. This text is how we would test it */
345    @Suppress
346    public void testHangulNameDecomposedSearch() {
347        createRawContactWithDisplayName("í길ë");
348
349        // the korean name uses three compound characters. this test makes sure
350        // that the name can be found by typing each syllable as a single character.
351        // This can be achieved using the Korean IM by pressing ã, space, backspace, ã and so on
352        assertStoredValue(buildSearchUri("ã"), SearchSnippetColumns.SNIPPET, null);
353        assertStoredValue(buildSearchUri("ãã"), SearchSnippetColumns.SNIPPET, null);
354        assertStoredValue(buildSearchUri("ããã"), SearchSnippetColumns.SNIPPET, null);
355        assertStoredValue(buildSearchUri("ãããã±"), SearchSnippetColumns.SNIPPET, null);
356        assertStoredValue(buildSearchUri("ãããã±ã£"), SearchSnippetColumns.SNIPPET, null);
357        assertStoredValue(buildSearchUri("ãããã±ã£ã¹"), SearchSnippetColumns.SNIPPET, null);
358        assertStoredValue(buildSearchUri("ãããã±ã£ã¹ã·"), SearchSnippetColumns.SNIPPET, null);
359        assertStoredValue(buildSearchUri("ãããã±ã£ã¹ã·ã"), SearchSnippetColumns.SNIPPET, null);
360        assertStoredValue(buildSearchUri("ãããã±ã£ã¹ã·ãã"), SearchSnippetColumns.SNIPPET, null);
361
362        // same again, this time only for the first name
363        assertStoredValue(buildSearchUri("ã±"), SearchSnippetColumns.SNIPPET, null);
364        assertStoredValue(buildSearchUri("ã±ã£"), SearchSnippetColumns.SNIPPET, null);
365        assertStoredValue(buildSearchUri("ã±ã£ã¹"), SearchSnippetColumns.SNIPPET, null);
366        assertStoredValue(buildSearchUri("ã±ã£ã¹ã·"), SearchSnippetColumns.SNIPPET, null);
367        assertStoredValue(buildSearchUri("ã±ã£ã¹ã·ã"), SearchSnippetColumns.SNIPPET, null);
368        assertStoredValue(buildSearchUri("ã±ã£ã¹ã·ãã"), SearchSnippetColumns.SNIPPET, null);
369    }
370
371    public void testNameWithHyphen() {
372        createRawContactWithName("First", "Last-name");
373
374        assertStoredValue(buildSearchUri("First"), SearchSnippetColumns.SNIPPET, null);
375        assertStoredValue(buildSearchUri("Last"), SearchSnippetColumns.SNIPPET, null);
376        assertStoredValue(buildSearchUri("Last-"), SearchSnippetColumns.SNIPPET, null);
377        assertStoredValue(buildSearchUri("Last-n"), SearchSnippetColumns.SNIPPET, null);
378        assertStoredValue(buildSearchUri("Last-name"), SearchSnippetColumns.SNIPPET, null);
379
380        // With the current implementation this even works, but this may stop working when we
381        // fix the "O'Neill" case below.
382        assertStoredValue(buildSearchUri("name"), SearchSnippetColumns.SNIPPET, null);
383    }
384
385    /** Same as {@link #testNameWithHyphen} except the name has double hyphens. */
386    public void testNameWithDoubleHyphens() {
387        createRawContactWithName("First", "Last--name");
388
389        assertStoredValue(buildSearchUri("First"), SearchSnippetColumns.SNIPPET, null);
390        assertStoredValue(buildSearchUri("Last"), SearchSnippetColumns.SNIPPET, null);
391        assertStoredValue(buildSearchUri("Last-"), SearchSnippetColumns.SNIPPET, null);
392        assertStoredValue(buildSearchUri("Last-n"), SearchSnippetColumns.SNIPPET, null);
393        assertStoredValue(buildSearchUri("Last-name"), SearchSnippetColumns.SNIPPET, null);
394    }
395
396    /**
397     * Probably both "oneill" and "o'neill" should match "o'neill", but at this point only "oneill"
398     * works.
399     */
400    @Suppress
401    public void testNameWithPunctuations() {
402        createRawContactWithName("First", "O'Neill");
403
404        assertStoredValue(buildSearchUri("first"), SearchSnippetColumns.SNIPPET, null);
405        assertStoredValue(buildSearchUri("oneill"), SearchSnippetColumns.SNIPPET, null);
406        assertStoredValue(buildSearchUri("o'neill"), SearchSnippetColumns.SNIPPET, null);
407    }
408
409    public void testSearchByEmailAddress() {
410        long rawContactId = createRawContact();
411        insertPhoneNumber(rawContactId, "1234567890");
412        insertEmail(rawContactId, "john@doe.com");
413        insertNote(rawContactId, "a hundred dollar note for doe@john.com and bob parr");
414
415        assertStoredValue(buildSearchUri("john@d", true), SearchSnippetColumns.SNIPPET,
416                "[john@doe.com]");
417        assertStoredValue(buildSearchUri("doe@j", true), SearchSnippetColumns.SNIPPET,
418                "...note for [doe@john.com] and bob...");
419        assertStoredValue(buildSearchUri("bob@p", true), SearchSnippetColumns.SNIPPET, null);
420    }
421
422    public void testSearchByPhoneNumber() {
423        long rawContactId = createRawContact();
424        insertPhoneNumber(rawContactId, "330142685300");
425        insertPhoneNumber(rawContactId, "(800)GOOG-123");
426        insertEmail(rawContactId, "john@doe.com");
427        insertNote(rawContactId, "the eighteenth episode of Seinfeld, 650-253-0000");
428
429        assertStoredValue(buildSearchUri("33 (0)1 42 68 53 00"), SearchSnippetColumns.SNIPPET,
430                "[330142685300]");
431        assertStoredValue(buildSearchUri("8004664"), SearchSnippetColumns.SNIPPET,
432                "[(800)GOOG-123]");
433        assertStoredValue(buildSearchUri("650-2"), SearchSnippetColumns.SNIPPET,
434                "...doe.com\nthe eighteenth episode of Seinfeld, [650]-[253]-0000");
435
436        // for numbers outside of the real phone field, any order (and prefixing) is allowed
437        assertStoredValue(buildSearchUri("25 650"), SearchSnippetColumns.SNIPPET,
438                "...doe.com\nthe eighteenth episode of Seinfeld, [650]-[253]-0000");
439    }
440
441    private Uri buildSearchUri(String filter) {
442        return buildSearchUri(filter, false);
443    }
444
445    private Uri buildSearchUri(String filter, boolean deferredSnippeting) {
446        return buildSearchUri(filter, null, deferredSnippeting);
447    }
448
449    private Uri buildSearchUri(String filter, String args, boolean deferredSnippeting) {
450        Builder builder = Contacts.CONTENT_FILTER_URI.buildUpon().appendPath(filter);
451        if (args != null) {
452            builder.appendQueryParameter(SearchSnippetColumns.SNIPPET_ARGS_PARAM_KEY, args);
453        }
454        if (deferredSnippeting) {
455            builder.appendQueryParameter(SearchSnippetColumns.DEFERRED_SNIPPETING_KEY, "1");
456        }
457        return builder.build();
458    }
459
460    private void createRawContactWithDisplayName(String name) {
461        long rawContactId = createRawContact();
462        ContentValues values = new ContentValues();
463        values.put(StructuredName.DISPLAY_NAME, name);
464        insertStructuredName(rawContactId, values);
465    }
466
467    // TODO: expectedName must be tested. Many tests in here are quite useless at the moment
468    private void assertSearchIndex(
469            long contactId, String expectedContent, String expectedName, String expectedTokens) {
470        ContactsDatabaseHelper dbHelper = (ContactsDatabaseHelper) getContactsProvider()
471                .getDatabaseHelper();
472        assertEquals(expectedContent, dbHelper.querySearchIndexContentForTest(contactId));
473        assertEquals(expectedTokens, dbHelper.querySearchIndexTokensForTest(contactId));
474    }
475}
476
477