Home | History | Annotate | Download | only in contacts
      1 /*
      2  * Copyright (C) 2010 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 
     17 package com.android.contacts;
     18 
     19 import android.content.Context;
     20 import android.database.CharArrayBuffer;
     21 import android.database.Cursor;
     22 import android.database.MatrixCursor;
     23 import android.provider.CallLog.Calls;
     24 import android.test.AndroidTestCase;
     25 import android.text.TextUtils;
     26 import android.view.View;
     27 import android.view.ViewGroup;
     28 
     29 import static com.android.contacts.GroupingListAdapter.ITEM_TYPE_STANDALONE;
     30 import static com.android.contacts.GroupingListAdapter.ITEM_TYPE_IN_GROUP;
     31 import static com.android.contacts.GroupingListAdapter.ITEM_TYPE_GROUP_HEADER;
     32 
     33 /**
     34  * Tests for the contact call list adapter.
     35  *
     36  * Running all tests:
     37  *
     38  *   runtest contacts
     39  * or
     40  *   adb shell am instrument \
     41  *     -w com.android.contacts.tests/android.test.InstrumentationTestRunner
     42  */
     43 public class GroupingListAdapterTests extends AndroidTestCase {
     44 
     45     static private final String[] CALL_LOG_PROJECTION = new String[] {
     46         Calls._ID,
     47         Calls.NUMBER,
     48         Calls.DATE,
     49     };
     50 
     51     private static final int CALLS_NUMBER_COLUMN_INDEX = 1;
     52 
     53     private MatrixCursor mCursor;
     54     private long mNextCall;
     55 
     56     private GroupingListAdapter mAdapter = new GroupingListAdapter(null) {
     57 
     58         @Override
     59         protected void addGroups(Cursor cursor) {
     60             int count = cursor.getCount();
     61             int groupItemCount = 1;
     62             cursor.moveToFirst();
     63             String currentValue = cursor.getString(CALLS_NUMBER_COLUMN_INDEX);
     64             for (int i = 1; i < count; i++) {
     65                 cursor.moveToNext();
     66                 String value = cursor.getString(CALLS_NUMBER_COLUMN_INDEX);
     67                 if (TextUtils.equals(value, currentValue)) {
     68                     groupItemCount++;
     69                 } else {
     70                     if (groupItemCount > 1) {
     71                         addGroup(i - groupItemCount, groupItemCount, false);
     72                     }
     73 
     74                     groupItemCount = 1;
     75                     currentValue = value;
     76                 }
     77             }
     78             if (groupItemCount > 1) {
     79                 addGroup(count - groupItemCount, groupItemCount, false);
     80             }
     81         }
     82 
     83         @Override
     84         protected void bindChildView(View view, Context context, Cursor cursor) {
     85         }
     86 
     87         @Override
     88         protected void bindGroupView(View view, Context context, Cursor cursor, int groupSize,
     89                 boolean expanded) {
     90         }
     91 
     92         @Override
     93         protected void bindStandAloneView(View view, Context context, Cursor cursor) {
     94         }
     95 
     96         @Override
     97         protected View newChildView(Context context, ViewGroup parent) {
     98             return null;
     99         }
    100 
    101         @Override
    102         protected View newGroupView(Context context, ViewGroup parent) {
    103             return null;
    104         }
    105 
    106         @Override
    107         protected View newStandAloneView(Context context, ViewGroup parent) {
    108             return null;
    109         }
    110     };
    111 
    112     private void buildCursor(String... numbers) {
    113         mCursor = new MatrixCursor(CALL_LOG_PROJECTION);
    114         mNextCall = 1;
    115         for (String number : numbers) {
    116             mCursor.addRow(new Object[]{mNextCall, number, 1000 - mNextCall});
    117             mNextCall++;
    118         }
    119     }
    120 
    121     public void testGroupingWithoutGroups() {
    122         buildCursor("1", "2", "3");
    123         mAdapter.changeCursor(mCursor);
    124 
    125         assertEquals(3, mAdapter.getCount());
    126         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
    127         assertPositionMetadata(1, ITEM_TYPE_STANDALONE, false, 1);
    128         assertPositionMetadata(2, ITEM_TYPE_STANDALONE, false, 2);
    129     }
    130 
    131     public void testGroupingWithCollapsedGroupAtTheBeginning() {
    132         buildCursor("1", "1", "2");
    133         mAdapter.changeCursor(mCursor);
    134 
    135         assertEquals(2, mAdapter.getCount());
    136         assertPositionMetadata(0, ITEM_TYPE_GROUP_HEADER, false, 0);
    137         assertPositionMetadata(1, ITEM_TYPE_STANDALONE, false, 2);
    138     }
    139 
    140     public void testGroupingWithExpandedGroupAtTheBeginning() {
    141         buildCursor("1", "1", "2");
    142         mAdapter.changeCursor(mCursor);
    143         mAdapter.toggleGroup(0);
    144 
    145         assertEquals(4, mAdapter.getCount());
    146         assertPositionMetadata(0, ITEM_TYPE_GROUP_HEADER, true, 0);
    147         assertPositionMetadata(1, ITEM_TYPE_IN_GROUP, false, 0);
    148         assertPositionMetadata(2, ITEM_TYPE_IN_GROUP, false, 1);
    149         assertPositionMetadata(3, ITEM_TYPE_STANDALONE, false, 2);
    150     }
    151 
    152     public void testGroupingWithExpandCollapseCycleAtTheBeginning() {
    153         buildCursor("1", "1", "2");
    154         mAdapter.changeCursor(mCursor);
    155         mAdapter.toggleGroup(0);
    156         mAdapter.toggleGroup(0);
    157 
    158         assertEquals(2, mAdapter.getCount());
    159         assertPositionMetadata(0, ITEM_TYPE_GROUP_HEADER, false, 0);
    160         assertPositionMetadata(1, ITEM_TYPE_STANDALONE, false, 2);
    161     }
    162 
    163     public void testGroupingWithCollapsedGroupInTheMiddle() {
    164         buildCursor("1", "2", "2", "2", "3");
    165         mAdapter.changeCursor(mCursor);
    166 
    167         assertEquals(3, mAdapter.getCount());
    168         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
    169         assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, false, 1);
    170         assertPositionMetadata(2, ITEM_TYPE_STANDALONE, false, 4);
    171     }
    172 
    173     public void testGroupingWithExpandedGroupInTheMiddle() {
    174         buildCursor("1", "2", "2", "2", "3");
    175         mAdapter.changeCursor(mCursor);
    176         mAdapter.toggleGroup(1);
    177 
    178         assertEquals(6, mAdapter.getCount());
    179         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
    180         assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, true, 1);
    181         assertPositionMetadata(2, ITEM_TYPE_IN_GROUP, false, 1);
    182         assertPositionMetadata(3, ITEM_TYPE_IN_GROUP, false, 2);
    183         assertPositionMetadata(4, ITEM_TYPE_IN_GROUP, false, 3);
    184         assertPositionMetadata(5, ITEM_TYPE_STANDALONE, false, 4);
    185     }
    186 
    187     public void testGroupingWithCollapsedGroupAtTheEnd() {
    188         buildCursor("1", "2", "3", "3", "3");
    189         mAdapter.changeCursor(mCursor);
    190 
    191         assertEquals(3, mAdapter.getCount());
    192         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
    193         assertPositionMetadata(1, ITEM_TYPE_STANDALONE, false, 1);
    194         assertPositionMetadata(2, ITEM_TYPE_GROUP_HEADER, false, 2);
    195     }
    196 
    197     public void testGroupingWithExpandedGroupAtTheEnd() {
    198         buildCursor("1", "2", "3", "3", "3");
    199         mAdapter.changeCursor(mCursor);
    200         mAdapter.toggleGroup(2);
    201 
    202         assertEquals(6, mAdapter.getCount());
    203         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
    204         assertPositionMetadata(1, ITEM_TYPE_STANDALONE, false, 1);
    205         assertPositionMetadata(2, ITEM_TYPE_GROUP_HEADER, true, 2);
    206         assertPositionMetadata(3, ITEM_TYPE_IN_GROUP, false, 2);
    207         assertPositionMetadata(4, ITEM_TYPE_IN_GROUP, false, 3);
    208         assertPositionMetadata(5, ITEM_TYPE_IN_GROUP, false, 4);
    209     }
    210 
    211     public void testGroupingWithMultipleCollapsedGroups() {
    212         buildCursor("1", "2", "2", "3", "4", "4", "5", "5", "6");
    213         mAdapter.changeCursor(mCursor);
    214 
    215         assertEquals(6, mAdapter.getCount());
    216         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
    217         assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, false, 1);
    218         assertPositionMetadata(2, ITEM_TYPE_STANDALONE, false, 3);
    219         assertPositionMetadata(3, ITEM_TYPE_GROUP_HEADER, false, 4);
    220         assertPositionMetadata(4, ITEM_TYPE_GROUP_HEADER, false, 6);
    221         assertPositionMetadata(5, ITEM_TYPE_STANDALONE, false, 8);
    222     }
    223 
    224     public void testGroupingWithMultipleExpandedGroups() {
    225         buildCursor("1", "2", "2", "3", "4", "4", "5", "5", "6");
    226         mAdapter.changeCursor(mCursor);
    227         mAdapter.toggleGroup(1);
    228 
    229         // Note that expanding the group of 2's shifted the group of 5's down from the
    230         // 4th to the 6th position
    231         mAdapter.toggleGroup(6);
    232 
    233         assertEquals(10, mAdapter.getCount());
    234         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
    235         assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, true, 1);
    236         assertPositionMetadata(2, ITEM_TYPE_IN_GROUP, false, 1);
    237         assertPositionMetadata(3, ITEM_TYPE_IN_GROUP, false, 2);
    238         assertPositionMetadata(4, ITEM_TYPE_STANDALONE, false, 3);
    239         assertPositionMetadata(5, ITEM_TYPE_GROUP_HEADER, false, 4);
    240         assertPositionMetadata(6, ITEM_TYPE_GROUP_HEADER, true, 6);
    241         assertPositionMetadata(7, ITEM_TYPE_IN_GROUP, false, 6);
    242         assertPositionMetadata(8, ITEM_TYPE_IN_GROUP, false, 7);
    243         assertPositionMetadata(9, ITEM_TYPE_STANDALONE, false, 8);
    244     }
    245 
    246     public void testPositionCache() {
    247         buildCursor("1", "2", "2", "3", "4", "4", "5", "5", "6");
    248         mAdapter.changeCursor(mCursor);
    249 
    250         // First pass - building up cache
    251         assertEquals(6, mAdapter.getCount());
    252         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
    253         assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, false, 1);
    254         assertPositionMetadata(2, ITEM_TYPE_STANDALONE, false, 3);
    255         assertPositionMetadata(3, ITEM_TYPE_GROUP_HEADER, false, 4);
    256         assertPositionMetadata(4, ITEM_TYPE_GROUP_HEADER, false, 6);
    257         assertPositionMetadata(5, ITEM_TYPE_STANDALONE, false, 8);
    258 
    259         // Second pass - using cache
    260         assertEquals(6, mAdapter.getCount());
    261         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
    262         assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, false, 1);
    263         assertPositionMetadata(2, ITEM_TYPE_STANDALONE, false, 3);
    264         assertPositionMetadata(3, ITEM_TYPE_GROUP_HEADER, false, 4);
    265         assertPositionMetadata(4, ITEM_TYPE_GROUP_HEADER, false, 6);
    266         assertPositionMetadata(5, ITEM_TYPE_STANDALONE, false, 8);
    267 
    268         // Invalidate cache by expanding a group
    269         mAdapter.toggleGroup(1);
    270 
    271         // First pass - building up cache
    272         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
    273         assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, true, 1);
    274         assertPositionMetadata(2, ITEM_TYPE_IN_GROUP, false, 1);
    275         assertPositionMetadata(3, ITEM_TYPE_IN_GROUP, false, 2);
    276         assertPositionMetadata(4, ITEM_TYPE_STANDALONE, false, 3);
    277         assertPositionMetadata(5, ITEM_TYPE_GROUP_HEADER, false, 4);
    278         assertPositionMetadata(6, ITEM_TYPE_GROUP_HEADER, false, 6);
    279         assertPositionMetadata(7, ITEM_TYPE_STANDALONE, false, 8);
    280 
    281         // Second pass - using cache
    282         assertPositionMetadata(0, ITEM_TYPE_STANDALONE, false, 0);
    283         assertPositionMetadata(1, ITEM_TYPE_GROUP_HEADER, true, 1);
    284         assertPositionMetadata(2, ITEM_TYPE_IN_GROUP, false, 1);
    285         assertPositionMetadata(3, ITEM_TYPE_IN_GROUP, false, 2);
    286         assertPositionMetadata(4, ITEM_TYPE_STANDALONE, false, 3);
    287         assertPositionMetadata(5, ITEM_TYPE_GROUP_HEADER, false, 4);
    288         assertPositionMetadata(6, ITEM_TYPE_GROUP_HEADER, false, 6);
    289         assertPositionMetadata(7, ITEM_TYPE_STANDALONE, false, 8);
    290     }
    291 
    292     public void testGroupDescriptorArrayGrowth() {
    293         String[] numbers = new String[500];
    294         for (int i = 0; i < numbers.length; i++) {
    295 
    296             // Make groups of 2
    297             numbers[i] = String.valueOf((i / 2) * 2);
    298         }
    299 
    300         buildCursor(numbers);
    301         mAdapter.changeCursor(mCursor);
    302 
    303         assertEquals(250, mAdapter.getCount());
    304     }
    305 
    306     private void assertPositionMetadata(int position, int itemType, boolean isExpanded,
    307             int cursorPosition) {
    308         GroupingListAdapter.PositionMetadata metadata = new GroupingListAdapter.PositionMetadata();
    309         mAdapter.obtainPositionMetadata(metadata, position);
    310         assertEquals(itemType, metadata.itemType);
    311         if (metadata.itemType == ITEM_TYPE_GROUP_HEADER) {
    312             assertEquals(isExpanded, metadata.isExpanded);
    313         }
    314         assertEquals(cursorPosition, metadata.cursorPosition);
    315     }
    316 }
    317