1 /*
2  * Copyright (C) 2016 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;
18 
19 import static junit.framework.Assert.assertTrue;
20 import static junit.framework.Assert.fail;
21 
22 import static org.junit.Assert.assertEquals;
23 
24 import android.content.Intent;
25 import android.net.Uri;
26 import android.os.Parcelable;
27 import android.provider.DocumentsContract;
28 import android.provider.DocumentsContract.Path;
29 
30 import androidx.recyclerview.selection.ItemDetailsLookup.ItemDetails;
31 import androidx.test.filters.MediumTest;
32 import androidx.test.runner.AndroidJUnit4;
33 
34 import com.android.documentsui.base.DocumentStack;
35 import com.android.documentsui.base.RootInfo;
36 import com.android.documentsui.base.Shared;
37 import com.android.documentsui.files.LauncherActivity;
38 import com.android.documentsui.sorting.SortDimension;
39 import com.android.documentsui.sorting.SortModel;
40 import com.android.documentsui.testing.DocumentStackAsserts;
41 import com.android.documentsui.testing.Roots;
42 import com.android.documentsui.testing.TestEnv;
43 import com.android.documentsui.testing.TestEventHandler;
44 import com.android.documentsui.testing.TestProvidersAccess;
45 
46 import org.junit.Before;
47 import org.junit.Test;
48 import org.junit.runner.RunWith;
49 
50 import java.util.Arrays;
51 import java.util.concurrent.CountDownLatch;
52 import java.util.concurrent.TimeUnit;
53 
54 /**
55  * A unit test *for* AbstractActionHandler, not an abstract test baseclass.
56  */
57 @RunWith(AndroidJUnit4.class)
58 @MediumTest
59 public class AbstractActionHandlerTest {
60 
61     private TestActivity mActivity;
62     private TestEnv mEnv;
63     private AbstractActionHandler<TestActivity> mHandler;
64 
65     @Before
setUp()66     public void setUp() {
67         mEnv = TestEnv.create();
68         mActivity = TestActivity.create(mEnv);
69         mHandler = new AbstractActionHandler<TestActivity>(
70                 mActivity,
71                 mEnv.state,
72                 mEnv.providers,
73                 mEnv.docs,
74                 mEnv.searchViewManager,
75                 mEnv::lookupExecutor,
76                 mEnv.injector) {
77 
78             @Override
79             public void openRoot(RootInfo root) {
80                 throw new UnsupportedOperationException();
81             }
82 
83             @Override
84             public boolean openItem(
85                     ItemDetails<String> doc, @ViewType int type, @ViewType int fallback) {
86                 throw new UnsupportedOperationException();
87             }
88 
89             @Override
90             public void initLocation(Intent intent) {
91                 throw new UnsupportedOperationException();
92             }
93 
94             @Override
95             protected void launchToDefaultLocation() {
96                 throw new UnsupportedOperationException();
97             }
98         };
99     }
100 
101     @Test
testOpenNewWindow()102     public void testOpenNewWindow() {
103         DocumentStack path = new DocumentStack(Roots.create("123"));
104         mHandler.openInNewWindow(path);
105 
106         Intent expected = LauncherActivity.createLaunchIntent(mActivity);
107         expected.putExtra(Shared.EXTRA_STACK, (Parcelable) path);
108         Intent actual = mActivity.startActivity.getLastValue();
109         assertEquals(expected.toString(), actual.toString());
110     }
111 
112     @Test
testOpensContainerDocuments_OpenFolderInSearch_JumpsToNewLocation()113     public void testOpensContainerDocuments_OpenFolderInSearch_JumpsToNewLocation()
114             throws Exception {
115         if (!mEnv.features.isLaunchToDocumentEnabled()) {
116             return;
117         }
118 
119         mEnv.populateStack();
120 
121         mEnv.searchViewManager.isSearching = true;
122         mEnv.docs.nextIsDocumentsUri = true;
123         mEnv.docs.nextPath = new Path(
124                 TestProvidersAccess.HOME.rootId,
125                 Arrays.asList(TestEnv.FOLDER_1.documentId, TestEnv.FOLDER_2.documentId));
126         mEnv.docs.nextDocuments = Arrays.asList(TestEnv.FOLDER_1, TestEnv.FOLDER_2);
127 
128         mHandler.openContainerDocument(TestEnv.FOLDER_2);
129 
130         mEnv.beforeAsserts();
131 
132         assertEquals(mEnv.docs.nextPath.getPath().size(), mEnv.state.stack.size());
133         assertEquals(TestEnv.FOLDER_2, mEnv.state.stack.pop());
134         assertEquals(TestEnv.FOLDER_1, mEnv.state.stack.pop());
135     }
136 
137 
138     @Test
testOpensContainerDocuments_ClickFolderInSearch_PushToRootDoc_NoFindPathSupport()139     public void testOpensContainerDocuments_ClickFolderInSearch_PushToRootDoc_NoFindPathSupport()
140             throws Exception {
141         mEnv.populateStack();
142 
143         mEnv.searchViewManager.isSearching = true;
144         mEnv.docs.nextIsDocumentsUri = true;
145         mEnv.docs.nextDocuments = Arrays.asList(TestEnv.FOLDER_1, TestEnv.FOLDER_2);
146 
147         mHandler.openContainerDocument(TestEnv.FOLDER_2);
148 
149         mEnv.beforeAsserts();
150 
151         assertEquals(2, mEnv.state.stack.size());
152         assertEquals(TestEnv.FOLDER_2, mEnv.state.stack.pop());
153         assertEquals(TestEnv.FOLDER_0, mEnv.state.stack.pop());
154     }
155 
156     @Test
testOpensContainerDocuments_ClickArchiveInSearch_opensArchiveInArchiveProvider()157     public void testOpensContainerDocuments_ClickArchiveInSearch_opensArchiveInArchiveProvider()
158             throws Exception {
159         if (!mEnv.features.isLaunchToDocumentEnabled()) {
160             return;
161         }
162 
163         mEnv.populateStack();
164 
165         mEnv.searchViewManager.isSearching = true;
166         mEnv.docs.nextIsDocumentsUri = true;
167         mEnv.docs.nextPath = new Path(
168                 TestProvidersAccess.HOME.rootId,
169                 Arrays.asList(TestEnv.FOLDER_1.documentId, TestEnv.FOLDER_2.documentId,
170                         TestEnv.FILE_ARCHIVE.documentId));
171         mEnv.docs.nextDocuments = Arrays.asList(
172                 TestEnv.FOLDER_1, TestEnv.FOLDER_2, TestEnv.FILE_ARCHIVE);
173         mEnv.docs.nextDocument = TestEnv.FILE_IN_ARCHIVE;
174 
175         mHandler.openContainerDocument(TestEnv.FILE_ARCHIVE);
176 
177         mEnv.beforeAsserts();
178 
179         assertEquals(mEnv.docs.nextPath.getPath().size(), mEnv.state.stack.size());
180         assertEquals(TestEnv.FILE_IN_ARCHIVE, mEnv.state.stack.pop());
181         assertEquals(TestEnv.FOLDER_2, mEnv.state.stack.pop());
182         assertEquals(TestEnv.FOLDER_1, mEnv.state.stack.pop());
183     }
184 
185     @Test
testOpensDocument_ExceptionIfAlreadyInStack()186     public void testOpensDocument_ExceptionIfAlreadyInStack() throws Exception {
187         mEnv.populateStack();
188         try {
189             mEnv.state.stack.push(TestEnv.FOLDER_0);
190             fail("Should have thrown IllegalArgumentException.");
191         } catch (IllegalArgumentException expected) {
192         }
193     }
194 
195     @Test
testLaunchToDocuments()196     public void testLaunchToDocuments() throws Exception {
197         if (!mEnv.features.isLaunchToDocumentEnabled()) {
198             return;
199         }
200 
201         mEnv.docs.nextIsDocumentsUri = true;
202         mEnv.docs.nextPath = new Path(
203                 TestProvidersAccess.HOME.rootId,
204                 Arrays.asList(
205                         TestEnv.FOLDER_0.documentId,
206                         TestEnv.FOLDER_1.documentId,
207                         TestEnv.FILE_GIF.documentId));
208         mEnv.docs.nextDocuments =
209                 Arrays.asList(TestEnv.FOLDER_0, TestEnv.FOLDER_1, TestEnv.FILE_GIF);
210 
211         mActivity.refreshCurrentRootAndDirectory.assertNotCalled();
212         assertTrue(mHandler.launchToDocument(TestEnv.FILE_GIF.derivedUri));
213 
214         mEnv.beforeAsserts();
215 
216         DocumentStackAsserts.assertEqualsTo(mEnv.state.stack, TestProvidersAccess.HOME,
217                 Arrays.asList(TestEnv.FOLDER_0, TestEnv.FOLDER_1));
218         mActivity.refreshCurrentRootAndDirectory.assertCalled();
219     }
220 
221     @Test
testLaunchToDocuments_convertsTreeUriToDocumentUri()222     public void testLaunchToDocuments_convertsTreeUriToDocumentUri() throws Exception {
223         if (!mEnv.features.isLaunchToDocumentEnabled()) {
224             return;
225         }
226 
227         mEnv.docs.nextIsDocumentsUri = true;
228         mEnv.docs.nextPath = new Path(
229                 TestProvidersAccess.HOME.rootId,
230                 Arrays.asList(
231                         TestEnv.FOLDER_0.documentId,
232                         TestEnv.FOLDER_1.documentId,
233                         TestEnv.FILE_GIF.documentId));
234         mEnv.docs.nextDocuments =
235                 Arrays.asList(TestEnv.FOLDER_0, TestEnv.FOLDER_1, TestEnv.FILE_GIF);
236 
237         final Uri treeBaseUri = DocumentsContract.buildTreeDocumentUri(
238                 TestProvidersAccess.HOME.authority, TestEnv.FOLDER_0.documentId);
239         final Uri treeDocUri = DocumentsContract.buildDocumentUriUsingTree(
240                 treeBaseUri, TestEnv.FILE_GIF.documentId);
241         assertTrue(mHandler.launchToDocument(treeDocUri));
242 
243         mEnv.beforeAsserts();
244 
245         DocumentStackAsserts.assertEqualsTo(mEnv.state.stack, TestProvidersAccess.HOME,
246                 Arrays.asList(TestEnv.FOLDER_0, TestEnv.FOLDER_1));
247         mEnv.docs.lastUri.assertLastArgument(TestEnv.FILE_GIF.derivedUri);
248         mActivity.refreshCurrentRootAndDirectory.assertCalled();
249     }
250 
251     @Test
testLoadChildrenDocuments()252     public void testLoadChildrenDocuments() throws Exception {
253         mEnv.state.stack.changeRoot(TestProvidersAccess.HOME);
254         mEnv.state.stack.push(TestEnv.FOLDER_0);
255 
256         mEnv.state.sortModel.sortByUser(
257                 SortModel.SORT_DIMENSION_ID_TITLE, SortDimension.SORT_DIRECTION_ASCENDING);
258 
259         mEnv.mockProviders.get(TestProvidersAccess.HOME.authority)
260                 .setNextChildDocumentsReturns(TestEnv.FILE_APK, TestEnv.FILE_GIF);
261 
262         mHandler.loadDocumentsForCurrentStack();
263         CountDownLatch latch = new CountDownLatch(1);
264         mEnv.model.addUpdateListener(event -> latch.countDown());
265         mActivity.supportLoaderManager.runAsyncTaskLoader(AbstractActionHandler.LOADER_ID);
266 
267         latch.await(1, TimeUnit.SECONDS);
268         assertEquals(2, mEnv.model.getItemCount());
269         String[] modelIds = mEnv.model.getModelIds();
270         assertEquals(TestEnv.FILE_APK, mEnv.model.getDocument(modelIds[0]));
271         assertEquals(TestEnv.FILE_GIF, mEnv.model.getDocument(modelIds[1]));
272     }
273 
274     @Test
testLoadChildrenDocuments_failsWithNonRecentsAndEmptyStack()275     public void testLoadChildrenDocuments_failsWithNonRecentsAndEmptyStack() throws Exception {
276         mEnv.state.stack.changeRoot(TestProvidersAccess.HOME);
277 
278         mEnv.mockProviders.get(TestProvidersAccess.HOME.authority)
279                 .setNextChildDocumentsReturns(TestEnv.FILE_APK, TestEnv.FILE_GIF);
280 
281         TestEventHandler<Model.Update> listener = new TestEventHandler<>();
282         mEnv.model.addUpdateListener(listener::accept);
283 
284         mHandler.loadDocumentsForCurrentStack();
285 
286         assertTrue(listener.getLastValue().hasException());
287     }
288 
289     @Test
testPreviewItem_throwException()290     public void testPreviewItem_throwException() throws Exception {
291         try {
292             mHandler.previewItem(null);
293             fail("Should have thrown UnsupportedOperationException.");
294         } catch (UnsupportedOperationException expected) {
295         }
296     }
297 }
298