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