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