Home | History | Annotate | Download | only in dirlist
      1 /*
      2  * Copyright (C) 2015 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.documentsui.dirlist;
     18 
     19 import android.support.v7.widget.RecyclerView;
     20 import android.test.AndroidTestCase;
     21 import android.test.suitebuilder.annotation.SmallTest;
     22 import android.util.SparseBooleanArray;
     23 
     24 import com.android.documentsui.TestInputEvent;
     25 import com.android.documentsui.dirlist.MultiSelectManager.Selection;
     26 import com.google.common.collect.Lists;
     27 
     28 import java.util.ArrayList;
     29 import java.util.HashSet;
     30 import java.util.List;
     31 import java.util.Set;
     32 
     33 @SmallTest
     34 public class MultiSelectManagerTest extends AndroidTestCase {
     35 
     36     private static final List<String> items;
     37     static {
     38         items = new ArrayList<String>();
     39         for (int i = 0; i < 100; ++i) {
     40             items.add(Integer.toString(i));
     41         }
     42     }
     43 
     44     private MultiSelectManager mManager;
     45     private TestCallback mCallback;
     46     private TestSelectionEnvironment mEnv;
     47     private TestDocumentsAdapter mAdapter;
     48 
     49     public void setUp() throws Exception {
     50         mCallback = new TestCallback();
     51         mEnv = new TestSelectionEnvironment(items);
     52         mAdapter = new TestDocumentsAdapter(items);
     53         mManager = new MultiSelectManager(mEnv, mAdapter, MultiSelectManager.MODE_MULTIPLE, null);
     54         mManager.addCallback(mCallback);
     55     }
     56 
     57     public void testSelection() {
     58         // Check selection.
     59         mManager.toggleSelection(items.get(7));
     60         assertSelection(items.get(7));
     61         // Check deselection.
     62         mManager.toggleSelection(items.get(7));
     63         assertSelectionSize(0);
     64     }
     65 
     66     public void testSelection_NotifiesSelectionChanged() {
     67         // Selection should notify.
     68         mManager.toggleSelection(items.get(7));
     69         mCallback.assertSelectionChanged();
     70         // Deselection should notify.
     71         mManager.toggleSelection(items.get(7));
     72         mCallback.assertSelectionChanged();
     73     }
     74 
     75     public void testMouseClick_ShiftClickExtendsSelection() {
     76         longPress(7);
     77         shiftClick(11);
     78         assertRangeSelection(7, 11);
     79     }
     80 
     81     public void testMouseClick_NoPosition_ClearsSelection() {
     82         longPress(7);
     83         click(11);
     84         click(RecyclerView.NO_POSITION);
     85         assertSelection();
     86     }
     87 
     88     public void testSetSelectionFocusBegin() {
     89         mManager.setItemsSelected(Lists.newArrayList(items.get(7)), true);
     90         mManager.setSelectionRangeBegin(7);
     91         shiftClick(11);
     92         assertRangeSelection(7, 11);
     93     }
     94 
     95     public void testLongPress_StartsSelectionMode() {
     96         longPress(7);
     97         assertSelection(items.get(7));
     98     }
     99 
    100     public void testLongPress_SecondPressExtendsSelection() {
    101         longPress(7);
    102         longPress(99);
    103         assertSelection(items.get(7), items.get(99));
    104     }
    105 
    106     public void testSingleTapUp_UnselectsSelectedItem() {
    107         longPress(7);
    108         tap(7);
    109         assertSelection();
    110     }
    111 
    112     public void testSingleTapUp_NoPosition_ClearsSelection() {
    113         longPress(7);
    114         tap(11);
    115         tap(RecyclerView.NO_POSITION);
    116         assertSelection();
    117     }
    118 
    119     public void testSingleTapUp_ExtendsSelection() {
    120         longPress(99);
    121         tap(7);
    122         tap(13);
    123         assertSelection(items.get(7), items.get(99), items.get(13));
    124     }
    125 
    126     public void testSingleTapUp_ShiftCreatesRangeSelection() {
    127         longPress(7);
    128         shiftTap(17);
    129         assertRangeSelection(7, 17);
    130     }
    131 
    132     public void testSingleTapUp_ShiftCreatesRangeSeletion_Backwards() {
    133         longPress(17);
    134         shiftTap(7);
    135         assertRangeSelection(7, 17);
    136     }
    137 
    138     public void testSingleTapUp_SecondShiftClickExtendsSelection() {
    139         longPress(7);
    140         shiftTap(11);
    141         shiftTap(17);
    142         assertRangeSelection(7, 17);
    143     }
    144 
    145     public void testSingleTapUp_MultipleContiguousRangesSelected() {
    146         longPress(7);
    147         shiftTap(11);
    148         tap(20);
    149         shiftTap(25);
    150         assertRangeSelected(7, 11);
    151         assertRangeSelected(20, 25);
    152         assertSelectionSize(11);
    153     }
    154 
    155     public void testSingleTapUp_ShiftReducesSelectionRange_FromPreviousShiftClick() {
    156         longPress(7);
    157         shiftTap(17);
    158         shiftTap(10);
    159         assertRangeSelection(7, 10);
    160     }
    161 
    162     public void testSingleTapUp_ShiftReducesSelectionRange_FromPreviousShiftClick_Backwards() {
    163         mManager.onLongPress(TestInputEvent.tap(17));
    164         shiftTap(7);
    165         shiftTap(14);
    166         assertRangeSelection(14, 17);
    167     }
    168 
    169     public void testSingleTapUp_ShiftReversesSelectionDirection() {
    170         longPress(7);
    171         shiftTap(17);
    172         shiftTap(0);
    173         assertRangeSelection(0, 7);
    174     }
    175 
    176     public void testSingleSelectMode() {
    177         mManager = new MultiSelectManager(mEnv, mAdapter, MultiSelectManager.MODE_SINGLE, null);
    178         mManager.addCallback(mCallback);
    179         longPress(20);
    180         tap(13);
    181         assertSelection(items.get(13));
    182     }
    183 
    184     public void testSingleSelectMode_ShiftTap() {
    185         mManager = new MultiSelectManager(mEnv, mAdapter, MultiSelectManager.MODE_SINGLE, null);
    186         mManager.addCallback(mCallback);
    187         longPress(13);
    188         shiftTap(20);
    189         assertSelection(items.get(20));
    190     }
    191 
    192     public void testRangeSelection() {
    193         mManager.startRangeSelection(15);
    194         mManager.snapRangeSelection(19);
    195         assertRangeSelection(15, 19);
    196     }
    197 
    198     public void testRangeSelection_snapExpand() {
    199         mManager.startRangeSelection(15);
    200         mManager.snapRangeSelection(19);
    201         mManager.snapRangeSelection(27);
    202         assertRangeSelection(15, 27);
    203     }
    204 
    205     public void testRangeSelection_snapContract() {
    206         mManager.startRangeSelection(15);
    207         mManager.snapRangeSelection(27);
    208         mManager.snapRangeSelection(19);
    209         assertRangeSelection(15, 19);
    210     }
    211 
    212     public void testRangeSelection_snapInvert() {
    213         mManager.startRangeSelection(15);
    214         mManager.snapRangeSelection(27);
    215         mManager.snapRangeSelection(3);
    216         assertRangeSelection(3, 15);
    217     }
    218 
    219     public void testRangeSelection_multiple() {
    220         mManager.startRangeSelection(15);
    221         mManager.snapRangeSelection(27);
    222         mManager.endRangeSelection();
    223         mManager.startRangeSelection(42);
    224         mManager.snapRangeSelection(57);
    225         assertSelectionSize(29);
    226         assertRangeSelected(15, 27);
    227         assertRangeSelected(42, 57);
    228 
    229     }
    230 
    231     public void testRangeSelection_singleSelect() {
    232         mManager = new MultiSelectManager(mEnv, mAdapter, MultiSelectManager.MODE_SINGLE, null);
    233         mManager.addCallback(mCallback);
    234         mManager.startRangeSelection(11);
    235         mManager.snapRangeSelection(19);
    236         assertSelectionSize(1);
    237         assertSelection(items.get(19));
    238     }
    239 
    240     public void testProvisionalSelection() {
    241         Selection s = mManager.getSelection();
    242         assertSelection();
    243 
    244         SparseBooleanArray provisional = new SparseBooleanArray();
    245         provisional.append(1, true);
    246         provisional.append(2, true);
    247         s.setProvisionalSelection(getItemIds(provisional));
    248         assertSelection(items.get(1), items.get(2));
    249     }
    250 
    251     public void testProvisionalSelection_Replace() {
    252         Selection s = mManager.getSelection();
    253 
    254         SparseBooleanArray provisional = new SparseBooleanArray();
    255         provisional.append(1, true);
    256         provisional.append(2, true);
    257         s.setProvisionalSelection(getItemIds(provisional));
    258 
    259         provisional.clear();
    260         provisional.append(3, true);
    261         provisional.append(4, true);
    262         s.setProvisionalSelection(getItemIds(provisional));
    263         assertSelection(items.get(3), items.get(4));
    264     }
    265 
    266     public void testProvisionalSelection_IntersectsExistingProvisionalSelection() {
    267         Selection s = mManager.getSelection();
    268 
    269         SparseBooleanArray provisional = new SparseBooleanArray();
    270         provisional.append(1, true);
    271         provisional.append(2, true);
    272         s.setProvisionalSelection(getItemIds(provisional));
    273 
    274         provisional.clear();
    275         provisional.append(1, true);
    276         s.setProvisionalSelection(getItemIds(provisional));
    277         assertSelection(items.get(1));
    278     }
    279 
    280     public void testProvisionalSelection_Apply() {
    281         Selection s = mManager.getSelection();
    282 
    283         SparseBooleanArray provisional = new SparseBooleanArray();
    284         provisional.append(1, true);
    285         provisional.append(2, true);
    286         s.setProvisionalSelection(getItemIds(provisional));
    287         s.applyProvisionalSelection();
    288         assertSelection(items.get(1), items.get(2));
    289     }
    290 
    291     public void testProvisionalSelection_Cancel() {
    292         mManager.toggleSelection(items.get(1));
    293         mManager.toggleSelection(items.get(2));
    294         Selection s = mManager.getSelection();
    295 
    296         SparseBooleanArray provisional = new SparseBooleanArray();
    297         provisional.append(3, true);
    298         provisional.append(4, true);
    299         s.setProvisionalSelection(getItemIds(provisional));
    300         s.cancelProvisionalSelection();
    301 
    302         // Original selection should remain.
    303         assertSelection(items.get(1), items.get(2));
    304     }
    305 
    306     public void testProvisionalSelection_IntersectsAppliedSelection() {
    307         mManager.toggleSelection(items.get(1));
    308         mManager.toggleSelection(items.get(2));
    309         Selection s = mManager.getSelection();
    310 
    311         SparseBooleanArray provisional = new SparseBooleanArray();
    312         provisional.append(2, true);
    313         provisional.append(3, true);
    314         s.setProvisionalSelection(getItemIds(provisional));
    315         assertSelection(items.get(1), items.get(2), items.get(3));
    316     }
    317 
    318     private static Set<String> getItemIds(SparseBooleanArray selection) {
    319         Set<String> ids = new HashSet<>();
    320 
    321         int count = selection.size();
    322         for (int i = 0; i < count; ++i) {
    323             ids.add(items.get(selection.keyAt(i)));
    324         }
    325 
    326         return ids;
    327     }
    328 
    329     private void longPress(int position) {
    330         mManager.onLongPress(TestInputEvent.tap(position));
    331     }
    332 
    333     private void tap(int position) {
    334         mManager.onSingleTapUp(TestInputEvent.tap(position));
    335     }
    336 
    337     private void shiftTap(int position) {
    338         mManager.onSingleTapUp(TestInputEvent.shiftTap(position));
    339     }
    340 
    341     private void click(int position) {
    342         mManager.onSingleTapUp(TestInputEvent.click(position));
    343     }
    344 
    345     private void shiftClick(int position) {
    346         mManager.onSingleTapUp(TestInputEvent.shiftClick(position));
    347     }
    348 
    349     private void assertSelected(String... expected) {
    350         for (int i = 0; i < expected.length; i++) {
    351             Selection selection = mManager.getSelection();
    352             String err = String.format(
    353                     "Selection %s does not contain %s", selection, expected[i]);
    354             assertTrue(err, selection.contains(expected[i]));
    355         }
    356     }
    357 
    358     private void assertSelection(String... expected) {
    359         assertSelectionSize(expected.length);
    360         assertSelected(expected);
    361     }
    362 
    363     private void assertRangeSelected(int begin, int end) {
    364         for (int i = begin; i <= end; i++) {
    365             assertSelected(items.get(i));
    366         }
    367     }
    368 
    369     private void assertRangeSelection(int begin, int end) {
    370         assertSelectionSize(end - begin + 1);
    371         assertRangeSelected(begin, end);
    372     }
    373 
    374     private void assertSelectionSize(int expected) {
    375         Selection selection = mManager.getSelection();
    376         assertEquals(selection.toString(), expected, selection.size());
    377     }
    378 
    379     private static final class TestCallback implements MultiSelectManager.Callback {
    380 
    381         Set<String> ignored = new HashSet<>();
    382         private boolean mSelectionChanged = false;
    383 
    384         @Override
    385         public void onItemStateChanged(String modelId, boolean selected) {}
    386 
    387         @Override
    388         public boolean onBeforeItemStateChange(String modelId, boolean selected) {
    389             return !ignored.contains(modelId);
    390         }
    391 
    392         @Override
    393         public void onSelectionChanged() {
    394             mSelectionChanged = true;
    395         }
    396 
    397         void assertSelectionChanged() {
    398             assertTrue(mSelectionChanged);
    399         }
    400     }
    401 }
    402