135997f3fdee2984b6d5373326110eda26929001aMakoto Onuki/* 235997f3fdee2984b6d5373326110eda26929001aMakoto Onuki * Copyright (C) 2012 The Android Open Source Project 335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki * 435997f3fdee2984b6d5373326110eda26929001aMakoto Onuki * Licensed under the Apache License, Version 2.0 (the "License"); 535997f3fdee2984b6d5373326110eda26929001aMakoto Onuki * you may not use this file except in compliance with the License. 635997f3fdee2984b6d5373326110eda26929001aMakoto Onuki * You may obtain a copy of the License at 735997f3fdee2984b6d5373326110eda26929001aMakoto Onuki * 835997f3fdee2984b6d5373326110eda26929001aMakoto Onuki * http://www.apache.org/licenses/LICENSE-2.0 935997f3fdee2984b6d5373326110eda26929001aMakoto Onuki * 1035997f3fdee2984b6d5373326110eda26929001aMakoto Onuki * Unless required by applicable law or agreed to in writing, software 1135997f3fdee2984b6d5373326110eda26929001aMakoto Onuki * distributed under the License is distributed on an "AS IS" BASIS, 1235997f3fdee2984b6d5373326110eda26929001aMakoto Onuki * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki * See the License for the specific language governing permissions and 1435997f3fdee2984b6d5373326110eda26929001aMakoto Onuki * limitations under the License 1535997f3fdee2984b6d5373326110eda26929001aMakoto Onuki */ 1635997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 1735997f3fdee2984b6d5373326110eda26929001aMakoto Onukipackage com.android.providers.contacts; 1835997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 1935997f3fdee2984b6d5373326110eda26929001aMakoto Onukiimport android.net.Uri; 2035997f3fdee2984b6d5373326110eda26929001aMakoto Onukiimport android.os.Bundle; 2135997f3fdee2984b6d5373326110eda26929001aMakoto Onukiimport android.provider.ContactsContract.ContactCounts; 2235997f3fdee2984b6d5373326110eda26929001aMakoto Onukiimport android.provider.ContactsContract.Contacts; 2335997f3fdee2984b6d5373326110eda26929001aMakoto Onukiimport android.provider.ContactsContract.RawContacts; 2435997f3fdee2984b6d5373326110eda26929001aMakoto Onukiimport android.test.AndroidTestCase; 2535997f3fdee2984b6d5373326110eda26929001aMakoto Onukiimport android.test.MoreAsserts; 2635997f3fdee2984b6d5373326110eda26929001aMakoto Onukiimport android.test.suitebuilder.annotation.SmallTest; 2735997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 2838210445730ee04c351c7cc1b3800cfe23e34325Makoto Onukiimport com.android.providers.contacts.util.MockSharedPreferences; 2938210445730ee04c351c7cc1b3800cfe23e34325Makoto Onuki 3035997f3fdee2984b6d5373326110eda26929001aMakoto Onuki@SmallTest 3135997f3fdee2984b6d5373326110eda26929001aMakoto Onukipublic class FastScrollingIndexCacheTest extends AndroidTestCase { 3235997f3fdee2984b6d5373326110eda26929001aMakoto Onuki private MockSharedPreferences mPrefs; 3335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki private FastScrollingIndexCache mCache; 3435997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 3535997f3fdee2984b6d5373326110eda26929001aMakoto Onuki private static final String[] TITLES_0 = new String[] {}; 3635997f3fdee2984b6d5373326110eda26929001aMakoto Onuki private static final String[] TITLES_1 = new String[] {"a"}; 3735997f3fdee2984b6d5373326110eda26929001aMakoto Onuki private static final String[] TITLES_2 = new String[] {"", "b"}; 3835997f3fdee2984b6d5373326110eda26929001aMakoto Onuki private static final String[] TITLES_3 = new String[] {"", "b", "aaa"}; 3935997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 4035997f3fdee2984b6d5373326110eda26929001aMakoto Onuki private static final int[] COUNTS_0 = new int[] {}; 4135997f3fdee2984b6d5373326110eda26929001aMakoto Onuki private static final int[] COUNTS_1 = new int[] {1}; 4235997f3fdee2984b6d5373326110eda26929001aMakoto Onuki private static final int[] COUNTS_2 = new int[] {2, 3}; 4335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki private static final int[] COUNTS_3 = new int[] {0, -1, 2}; 4435997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 4535997f3fdee2984b6d5373326110eda26929001aMakoto Onuki private static final String[] PROJECTION_0 = new String[] {}; 4635997f3fdee2984b6d5373326110eda26929001aMakoto Onuki private static final String[] PROJECTION_1 = new String[] {"c1"}; 4735997f3fdee2984b6d5373326110eda26929001aMakoto Onuki private static final String[] PROJECTION_2 = new String[] {"c3", "c4"}; 4835997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 4935997f3fdee2984b6d5373326110eda26929001aMakoto Onuki private static final Uri URI_A = Contacts.CONTENT_URI; 5035997f3fdee2984b6d5373326110eda26929001aMakoto Onuki private static final Uri URI_B = RawContacts.CONTENT_URI; 5135997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 5235997f3fdee2984b6d5373326110eda26929001aMakoto Onuki @Override 5335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki protected void setUp() throws Exception { 5435997f3fdee2984b6d5373326110eda26929001aMakoto Onuki super.setUp(); 5535997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 5635997f3fdee2984b6d5373326110eda26929001aMakoto Onuki mPrefs = new MockSharedPreferences(); 5735997f3fdee2984b6d5373326110eda26929001aMakoto Onuki mCache = new FastScrollingIndexCache(mPrefs); 5835997f3fdee2984b6d5373326110eda26929001aMakoto Onuki } 5935997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 6035997f3fdee2984b6d5373326110eda26929001aMakoto Onuki private void assertBundle(String[] expectedTitles, int[] expectedCounts, Bundle actual) { 6135997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertNotNull(actual); 6235997f3fdee2984b6d5373326110eda26929001aMakoto Onuki MoreAsserts.assertEquals(expectedTitles, 6335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki actual.getStringArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_TITLES)); 6435997f3fdee2984b6d5373326110eda26929001aMakoto Onuki MoreAsserts.assertEquals(expectedCounts, 6535997f3fdee2984b6d5373326110eda26929001aMakoto Onuki actual.getIntArray(ContactCounts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS)); 6635997f3fdee2984b6d5373326110eda26929001aMakoto Onuki } 6735997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 6835997f3fdee2984b6d5373326110eda26929001aMakoto Onuki /** 6935997f3fdee2984b6d5373326110eda26929001aMakoto Onuki * Test for {@link FastScrollingIndexCache#buildExtraBundleFromValue} and 7035997f3fdee2984b6d5373326110eda26929001aMakoto Onuki * {@link FastScrollingIndexCache#buildCacheValue}. 7135997f3fdee2984b6d5373326110eda26929001aMakoto Onuki */ 7235997f3fdee2984b6d5373326110eda26929001aMakoto Onuki public void testBuildCacheValue() { 7335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_0, COUNTS_0, 7435997f3fdee2984b6d5373326110eda26929001aMakoto Onuki FastScrollingIndexCache.buildExtraBundleFromValue( 7535997f3fdee2984b6d5373326110eda26929001aMakoto Onuki FastScrollingIndexCache.buildCacheValue(TITLES_0, COUNTS_0))); 7635997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_1, COUNTS_1, 7735997f3fdee2984b6d5373326110eda26929001aMakoto Onuki FastScrollingIndexCache.buildExtraBundleFromValue( 7835997f3fdee2984b6d5373326110eda26929001aMakoto Onuki FastScrollingIndexCache.buildCacheValue(TITLES_1, COUNTS_1))); 7935997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_2, COUNTS_2, 8035997f3fdee2984b6d5373326110eda26929001aMakoto Onuki FastScrollingIndexCache.buildExtraBundleFromValue( 8135997f3fdee2984b6d5373326110eda26929001aMakoto Onuki FastScrollingIndexCache.buildCacheValue(TITLES_2, COUNTS_2))); 8235997f3fdee2984b6d5373326110eda26929001aMakoto Onuki } 8335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 845acb3e091bc334d4e0f367a36f8d62a0add02b39Makoto Onuki private static final Bundle putAndGetBundle(FastScrollingIndexCache cache, Uri queryUri, 855acb3e091bc334d4e0f367a36f8d62a0add02b39Makoto Onuki String selection, String[] selectionArgs, String sortOrder, String countExpression, 865acb3e091bc334d4e0f367a36f8d62a0add02b39Makoto Onuki String[] titles, int[] counts) { 875acb3e091bc334d4e0f367a36f8d62a0add02b39Makoto Onuki Bundle bundle = FastScrollingIndexCache.buildExtraBundle(titles, counts); 885acb3e091bc334d4e0f367a36f8d62a0add02b39Makoto Onuki cache.put(queryUri, selection, selectionArgs, sortOrder, countExpression, bundle); 895acb3e091bc334d4e0f367a36f8d62a0add02b39Makoto Onuki return bundle; 905acb3e091bc334d4e0f367a36f8d62a0add02b39Makoto Onuki } 915acb3e091bc334d4e0f367a36f8d62a0add02b39Makoto Onuki 9235997f3fdee2984b6d5373326110eda26929001aMakoto Onuki public void testPutAndGet() { 9335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki // Initially the cache is empty 9435997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertNull(mCache.get(null, null, null, null, null)); 9535997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertNull(mCache.get(URI_A, "*s*", PROJECTION_0, "*so*", "*ce*")); 9635997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertNull(mCache.get(URI_A, "*s*", PROJECTION_1, "*so*", "*ce*")); 9735997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertNull(mCache.get(URI_B, "s", PROJECTION_2, "so", "ce")); 9835997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 9935997f3fdee2984b6d5373326110eda26929001aMakoto Onuki // Put... 10035997f3fdee2984b6d5373326110eda26929001aMakoto Onuki Bundle b; 1015acb3e091bc334d4e0f367a36f8d62a0add02b39Makoto Onuki b = putAndGetBundle(mCache, null, null, null, null, null, TITLES_0, COUNTS_0); 10235997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_0, COUNTS_0, b); 10335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 1045acb3e091bc334d4e0f367a36f8d62a0add02b39Makoto Onuki b = putAndGetBundle(mCache, URI_A, "*s*", PROJECTION_0, "*so*", "*ce*", TITLES_1, COUNTS_1); 10535997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_1, COUNTS_1, b); 10635997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 1075acb3e091bc334d4e0f367a36f8d62a0add02b39Makoto Onuki b = putAndGetBundle(mCache, URI_A, "*s*", PROJECTION_1, "*so*", "*ce*", TITLES_2, COUNTS_2); 10835997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_2, COUNTS_2, b); 10935997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 1105acb3e091bc334d4e0f367a36f8d62a0add02b39Makoto Onuki b = putAndGetBundle(mCache, URI_B, "s", PROJECTION_2, "so", "ce", TITLES_3, COUNTS_3); 11135997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_3, COUNTS_3, b); 11235997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 11335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki // Get... 11435997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_0, COUNTS_0, mCache.get(null, null, null, null, null)); 11535997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_1, COUNTS_1, mCache.get(URI_A, "*s*", PROJECTION_0, "*so*", "*ce*")); 11635997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_2, COUNTS_2, mCache.get(URI_A, "*s*", PROJECTION_1, "*so*", "*ce*")); 11735997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_3, COUNTS_3, mCache.get(URI_B, "s", PROJECTION_2, "so", "ce")); 11835997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 11935997f3fdee2984b6d5373326110eda26929001aMakoto Onuki // Invalidate... 12035997f3fdee2984b6d5373326110eda26929001aMakoto Onuki mCache.invalidate(); 12135997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 12235997f3fdee2984b6d5373326110eda26929001aMakoto Onuki // Get again... Nothing shoul be cached... 12335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertNull(mCache.get(null, null, null, null, null)); 12435997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertNull(mCache.get(URI_A, "*s*", PROJECTION_0, "*so*", "*ce*")); 12535997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertNull(mCache.get(URI_A, "*s*", PROJECTION_1, "*so*", "*ce*")); 12635997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertNull(mCache.get(URI_B, "s", PROJECTION_2, "so", "ce")); 12735997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 12835997f3fdee2984b6d5373326110eda26929001aMakoto Onuki // Put again... 1295acb3e091bc334d4e0f367a36f8d62a0add02b39Makoto Onuki b = putAndGetBundle(mCache, null, null, null, null, null, TITLES_0, COUNTS_0); 13035997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_0, COUNTS_0, b); 13135997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 1325acb3e091bc334d4e0f367a36f8d62a0add02b39Makoto Onuki b = putAndGetBundle(mCache, URI_A, "*s*", PROJECTION_0, "*so*", "*ce*", TITLES_1, COUNTS_1); 13335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_1, COUNTS_1, b); 13435997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 1355acb3e091bc334d4e0f367a36f8d62a0add02b39Makoto Onuki b = putAndGetBundle(mCache, URI_A, "*s*", PROJECTION_1, "*so*", "*ce*", TITLES_2, COUNTS_2); 13635997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_2, COUNTS_2, b); 13735997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 1385acb3e091bc334d4e0f367a36f8d62a0add02b39Makoto Onuki b = putAndGetBundle(mCache, URI_B, "s", PROJECTION_2, "so", "ce", TITLES_2, COUNTS_2); 13935997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_2, COUNTS_2, b); 14035997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 14135997f3fdee2984b6d5373326110eda26929001aMakoto Onuki // Now, create a new cache instance (with the same shared preferences) 14235997f3fdee2984b6d5373326110eda26929001aMakoto Onuki // It should restore the cache content from the preferences... 14335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 14435997f3fdee2984b6d5373326110eda26929001aMakoto Onuki FastScrollingIndexCache cache2 = new FastScrollingIndexCache(mPrefs); 14535997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_0, COUNTS_0, cache2.get(null, null, null, null, null)); 14635997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_1, COUNTS_1, cache2.get(URI_A, "*s*", PROJECTION_0, "*so*", "*ce*")); 14735997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_2, COUNTS_2, cache2.get(URI_A, "*s*", PROJECTION_1, "*so*", "*ce*")); 14835997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertBundle(TITLES_2, COUNTS_2, cache2.get(URI_B, "s", PROJECTION_2, "so", "ce")); 14935997f3fdee2984b6d5373326110eda26929001aMakoto Onuki } 15035997f3fdee2984b6d5373326110eda26929001aMakoto Onuki 15135997f3fdee2984b6d5373326110eda26929001aMakoto Onuki public void testMalformedPreferences() { 15235997f3fdee2984b6d5373326110eda26929001aMakoto Onuki mPrefs.edit().putString(FastScrollingIndexCache.PREFERENCE_KEY, "123"); 15335997f3fdee2984b6d5373326110eda26929001aMakoto Onuki // get() shouldn't crash 15435997f3fdee2984b6d5373326110eda26929001aMakoto Onuki assertNull(mCache.get(null, null, null, null, null)); 15535997f3fdee2984b6d5373326110eda26929001aMakoto Onuki } 15635997f3fdee2984b6d5373326110eda26929001aMakoto Onuki} 157