• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.selection;
18 
19 import android.support.test.filters.SmallTest;
20 import android.support.test.runner.AndroidJUnit4;
21 import android.util.SparseBooleanArray;
22 
23 import com.android.documentsui.dirlist.TestDocumentsAdapter;
24 import com.android.documentsui.selection.SelectionManager;
25 import com.android.documentsui.dirlist.TestData;
26 import com.android.documentsui.selection.Selection;
27 import com.android.documentsui.testing.SelectionManagers;
28 
29 import org.junit.Before;
30 import org.junit.Test;
31 import org.junit.runner.RunWith;
32 
33 import java.util.ArrayList;
34 import java.util.HashSet;
35 import java.util.List;
36 import java.util.Set;
37 
38 @RunWith(AndroidJUnit4.class)
39 @SmallTest
40 public class SelectionManagerTest {
41 
42     private static final List<String> ITEMS = TestData.create(100);
43 
44     private final Set<String> mIgnored = new HashSet<>();
45     private TestDocumentsAdapter mAdapter;
46     private SelectionManager mManager;
47     private TestSelectionListener mCallback;
48     private TestItemSelectionListener mItemCallback;
49     private SelectionProbe mSelection;
50 
51     @Before
setUp()52     public void setUp() throws Exception {
53         mCallback = new TestSelectionListener();
54         mItemCallback = new TestItemSelectionListener();
55         mAdapter = new TestDocumentsAdapter(ITEMS);
56         mManager = SelectionManagers.createTestInstance(
57                 mAdapter,
58                 SelectionManager.MODE_MULTIPLE,
59                 (String id, boolean nextState) -> (!nextState || !mIgnored.contains(id)));
60         mManager.addCallback(mCallback);
61         mManager.addItemCallback(mItemCallback);
62 
63         mSelection = new SelectionProbe(mManager, mItemCallback);
64 
65         mIgnored.clear();
66     }
67 
68     @Test
testSelection()69     public void testSelection() {
70         // Check selection.
71         mManager.toggleSelection(ITEMS.get(7));
72         mSelection.assertSelection(7);
73         // Check deselection.
74         mManager.toggleSelection(ITEMS.get(7));
75         mSelection.assertNoSelection();
76     }
77 
78     @Test
testSelection_DoNothingOnUnselectableItem()79     public void testSelection_DoNothingOnUnselectableItem() {
80         mIgnored.add(ITEMS.get(7));
81 
82         mManager.toggleSelection(ITEMS.get(7));
83         mSelection.assertNoSelection();
84     }
85 
86     @Test
testSelection_NotifiesSelectionChanged()87     public void testSelection_NotifiesSelectionChanged() {
88         // Selection should notify.
89         mManager.toggleSelection(ITEMS.get(7));
90         mCallback.assertSelectionChanged();
91         // Deselection should notify.
92         mManager.toggleSelection(ITEMS.get(7));
93         mCallback.assertSelectionChanged();
94     }
95 
96     @Test
testSelection_PersistsOnUpdate()97     public void testSelection_PersistsOnUpdate() {
98         mManager.toggleSelection(ITEMS.get(7));
99 
100         mAdapter.updateTestModelIds(ITEMS);
101 
102         mSelection.assertSelection(7);
103     }
104 
105     @Test
testSelection_IntersectsWithNewDataSet()106     public void testSelection_IntersectsWithNewDataSet() {
107         mManager.toggleSelection(ITEMS.get(99));
108         mManager.toggleSelection(ITEMS.get(7));
109 
110         mAdapter.updateTestModelIds(TestData.create(50));
111 
112         mSelection.assertSelection(7);
113     }
114 
115     @Test
testSetItemsSelected()116     public void testSetItemsSelected() {
117         mManager.setItemsSelected(getStringIds(6, 7, 8), true);
118 
119         mSelection.assertRangeSelected(6, 8);
120     }
121 
122     @Test
testSetItemsSelected_SkipUnselectableItem()123     public void testSetItemsSelected_SkipUnselectableItem() {
124         mIgnored.add(ITEMS.get(7));
125 
126         mManager.setItemsSelected(getStringIds(6, 7, 8), true);
127 
128         mSelection.assertSelected(6);
129         mSelection.assertNotSelected(7);
130         mSelection.assertSelected(8);
131     }
132 
133     @Test
testRangeSelection()134     public void testRangeSelection() {
135         mManager.startRangeSelection(15);
136         mManager.snapRangeSelection(19);
137         mSelection.assertRangeSelection(15, 19);
138     }
139 
140     @Test
testRangeSelection_SkipUnselectableItem()141     public void testRangeSelection_SkipUnselectableItem() {
142         mIgnored.add(ITEMS.get(17));
143 
144         mManager.startRangeSelection(15);
145         mManager.snapRangeSelection(19);
146 
147         mSelection.assertRangeSelected(15, 16);
148         mSelection.assertNotSelected(17);
149         mSelection.assertRangeSelected(18, 19);
150     }
151 
152     @Test
testRangeSelection_snapExpand()153     public void testRangeSelection_snapExpand() {
154         mManager.startRangeSelection(15);
155         mManager.snapRangeSelection(19);
156         mManager.snapRangeSelection(27);
157         mSelection.assertRangeSelection(15, 27);
158     }
159 
160     @Test
testRangeSelection_snapContract()161     public void testRangeSelection_snapContract() {
162         mManager.startRangeSelection(15);
163         mManager.snapRangeSelection(27);
164         mManager.snapRangeSelection(19);
165         mSelection.assertRangeSelection(15, 19);
166     }
167 
168     @Test
testRangeSelection_snapInvert()169     public void testRangeSelection_snapInvert() {
170         mManager.startRangeSelection(15);
171         mManager.snapRangeSelection(27);
172         mManager.snapRangeSelection(3);
173         mSelection.assertRangeSelection(3, 15);
174     }
175 
176     @Test
testRangeSelection_multiple()177     public void testRangeSelection_multiple() {
178         mManager.startRangeSelection(15);
179         mManager.snapRangeSelection(27);
180         mManager.endRangeSelection();
181         mManager.startRangeSelection(42);
182         mManager.snapRangeSelection(57);
183         mSelection.assertSelectionSize(29);
184         mSelection.assertRangeSelected(15, 27);
185         mSelection.assertRangeSelected(42, 57);
186     }
187 
188     @Test
testProvisionalRangeSelection()189     public void testProvisionalRangeSelection() {
190         mManager.startRangeSelection(13);
191         mManager.snapProvisionalRangeSelection(15);
192         mSelection.assertRangeSelection(13, 15);
193         mManager.getSelection().applyProvisionalSelection();
194         mManager.endRangeSelection();
195         mSelection.assertSelectionSize(3);
196     }
197 
198     @Test
testProvisionalRangeSelection_endEarly()199     public void testProvisionalRangeSelection_endEarly() {
200         mManager.startRangeSelection(13);
201         mManager.snapProvisionalRangeSelection(15);
202         mSelection.assertRangeSelection(13, 15);
203 
204         mManager.endRangeSelection();
205         // If we end range selection prematurely for provision selection, nothing should be selected
206         // except the first item
207         mSelection.assertSelectionSize(1);
208     }
209 
210     @Test
testProvisionalRangeSelection_snapExpand()211     public void testProvisionalRangeSelection_snapExpand() {
212         mManager.startRangeSelection(13);
213         mManager.snapProvisionalRangeSelection(15);
214         mSelection.assertRangeSelection(13, 15);
215         mManager.getSelection().applyProvisionalSelection();
216         mManager.snapRangeSelection(18);
217         mSelection.assertRangeSelection(13, 18);
218     }
219 
220     @Test
testCombinationRangeSelection_IntersectsOldSelection()221     public void testCombinationRangeSelection_IntersectsOldSelection() {
222         mManager.startRangeSelection(13);
223         mManager.snapRangeSelection(15);
224         mSelection.assertRangeSelection(13, 15);
225 
226         mManager.startRangeSelection(11);
227         mManager.snapProvisionalRangeSelection(18);
228         mSelection.assertRangeSelected(11, 18);
229         mManager.endRangeSelection();
230         mSelection.assertRangeSelected(13, 15);
231         mSelection.assertRangeSelected(11, 11);
232         mSelection.assertSelectionSize(4);
233     }
234 
235     @Test
testProvisionalSelection()236     public void testProvisionalSelection() {
237         Selection s = mManager.getSelection();
238         mSelection.assertNoSelection();
239 
240         // Mimicking band selection case -- BandController notifies item callback by itself.
241         mItemCallback.onItemStateChanged(ITEMS.get(1), true);
242         mItemCallback.onItemStateChanged(ITEMS.get(2), true);
243 
244         SparseBooleanArray provisional = new SparseBooleanArray();
245         provisional.append(1, true);
246         provisional.append(2, true);
247         s.setProvisionalSelection(getItemIds(provisional));
248         mSelection.assertSelection(1, 2);
249     }
250 
251     @Test
testProvisionalSelection_Replace()252     public void testProvisionalSelection_Replace() {
253         Selection s = mManager.getSelection();
254 
255         // Mimicking band selection case -- BandController notifies item callback by itself.
256         mItemCallback.onItemStateChanged(ITEMS.get(1), true);
257         mItemCallback.onItemStateChanged(ITEMS.get(2), true);
258         SparseBooleanArray provisional = new SparseBooleanArray();
259         provisional.append(1, true);
260         provisional.append(2, true);
261         s.setProvisionalSelection(getItemIds(provisional));
262 
263         mItemCallback.onItemStateChanged(ITEMS.get(1), false);
264         mItemCallback.onItemStateChanged(ITEMS.get(2), false);
265         provisional.clear();
266 
267         mItemCallback.onItemStateChanged(ITEMS.get(3), true);
268         mItemCallback.onItemStateChanged(ITEMS.get(4), true);
269         provisional.append(3, true);
270         provisional.append(4, true);
271         s.setProvisionalSelection(getItemIds(provisional));
272         mSelection.assertSelection(3, 4);
273     }
274 
275     @Test
testProvisionalSelection_IntersectsExistingProvisionalSelection()276     public void testProvisionalSelection_IntersectsExistingProvisionalSelection() {
277         Selection s = mManager.getSelection();
278 
279         // Mimicking band selection case -- BandController notifies item callback by itself.
280         mItemCallback.onItemStateChanged(ITEMS.get(1), true);
281         mItemCallback.onItemStateChanged(ITEMS.get(2), true);
282         SparseBooleanArray provisional = new SparseBooleanArray();
283         provisional.append(1, true);
284         provisional.append(2, true);
285         s.setProvisionalSelection(getItemIds(provisional));
286 
287         mItemCallback.onItemStateChanged(ITEMS.get(1), false);
288         mItemCallback.onItemStateChanged(ITEMS.get(2), false);
289         provisional.clear();
290 
291         mItemCallback.onItemStateChanged(ITEMS.get(1), true);
292         provisional.append(1, true);
293         s.setProvisionalSelection(getItemIds(provisional));
294         mSelection.assertSelection(1);
295     }
296 
297     @Test
testProvisionalSelection_Apply()298     public void testProvisionalSelection_Apply() {
299         Selection s = mManager.getSelection();
300 
301         // Mimicking band selection case -- BandController notifies item callback by itself.
302         mItemCallback.onItemStateChanged(ITEMS.get(1), true);
303         mItemCallback.onItemStateChanged(ITEMS.get(2), true);
304         SparseBooleanArray provisional = new SparseBooleanArray();
305         provisional.append(1, true);
306         provisional.append(2, true);
307         s.setProvisionalSelection(getItemIds(provisional));
308         s.applyProvisionalSelection();
309 
310         mSelection.assertSelection(1, 2);
311     }
312 
313     @Test
testProvisionalSelection_Cancel()314     public void testProvisionalSelection_Cancel() {
315         mManager.toggleSelection(ITEMS.get(1));
316         mManager.toggleSelection(ITEMS.get(2));
317         Selection s = mManager.getSelection();
318 
319         SparseBooleanArray provisional = new SparseBooleanArray();
320         provisional.append(3, true);
321         provisional.append(4, true);
322         s.setProvisionalSelection(getItemIds(provisional));
323         s.cancelProvisionalSelection();
324 
325         // Original selection should remain.
326         mSelection.assertSelection(1, 2);
327     }
328 
329     @Test
testProvisionalSelection_IntersectsAppliedSelection()330     public void testProvisionalSelection_IntersectsAppliedSelection() {
331         mManager.toggleSelection(ITEMS.get(1));
332         mManager.toggleSelection(ITEMS.get(2));
333         Selection s = mManager.getSelection();
334 
335         // Mimicking band selection case -- BandController notifies item callback by itself.
336         mItemCallback.onItemStateChanged(ITEMS.get(3), true);
337         SparseBooleanArray provisional = new SparseBooleanArray();
338         provisional.append(2, true);
339         provisional.append(3, true);
340         s.setProvisionalSelection(getItemIds(provisional));
341         mSelection.assertSelection(1, 2, 3);
342     }
343 
getItemIds(SparseBooleanArray selection)344     private static Set<String> getItemIds(SparseBooleanArray selection) {
345         Set<String> ids = new HashSet<>();
346 
347         int count = selection.size();
348         for (int i = 0; i < count; ++i) {
349             ids.add(ITEMS.get(selection.keyAt(i)));
350         }
351 
352         return ids;
353     }
354 
getStringIds(int... ids)355     private static Iterable<String> getStringIds(int... ids) {
356         List<String> stringIds = new ArrayList<>(ids.length);
357         for (int id : ids) {
358             stringIds.add(ITEMS.get(id));
359         }
360         return stringIds;
361     }
362 }
363