| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.documentsui; |
| |
| import static com.google.common.truth.Truth.assertThat; |
| |
| import static junit.framework.Assert.assertEquals; |
| import static junit.framework.Assert.assertTrue; |
| |
| import android.database.Cursor; |
| import android.os.Bundle; |
| import android.provider.DocumentsContract; |
| import android.provider.DocumentsContract.Document; |
| |
| import androidx.test.filters.MediumTest; |
| |
| import com.android.documentsui.base.DocumentInfo; |
| import com.android.documentsui.base.State; |
| import com.android.documentsui.sorting.SortDimension; |
| import com.android.documentsui.sorting.SortModel; |
| import com.android.documentsui.testing.ActivityManagers; |
| import com.android.documentsui.testing.TestEnv; |
| import com.android.documentsui.testing.TestFileTypeLookup; |
| import com.android.documentsui.testing.TestImmediateExecutor; |
| import com.android.documentsui.testing.TestProvidersAccess; |
| import com.android.modules.utils.build.SdkLevel; |
| |
| import com.google.common.collect.Lists; |
| |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.Parameterized; |
| import org.junit.runners.Parameterized.Parameter; |
| import org.junit.runners.Parameterized.Parameters; |
| |
| @RunWith(Parameterized.class) |
| @MediumTest |
| public class GlobalSearchLoaderTest { |
| |
| private static final String SEARCH_STRING = "freddy"; |
| private static int FILE_FLAG = Document.FLAG_SUPPORTS_MOVE | Document.FLAG_SUPPORTS_DELETE |
| | Document.FLAG_SUPPORTS_REMOVE; |
| |
| private TestEnv mEnv; |
| private TestActivity mActivity; |
| private GlobalSearchLoader mLoader; |
| private TestConfigStore mTestConfigStore; |
| private Bundle mQueryArgs = new Bundle(); |
| |
| @Parameter(0) |
| public boolean isPrivateSpaceEnabled; |
| |
| /** |
| * Parametrize values for {@code isPrivateSpaceEnabled} to run all the tests twice once with |
| * private space flag enabled and once with it disabled. |
| */ |
| @Parameters(name = "privateSpaceEnabled={0}") |
| public static Iterable<?> data() { |
| return Lists.newArrayList(true, false); |
| } |
| |
| @Before |
| public void setUp() { |
| mEnv = TestEnv.create(); |
| mActivity = TestActivity.create(mEnv); |
| mActivity.activityManager = ActivityManagers.create(false); |
| mTestConfigStore = new TestConfigStore(); |
| mEnv.state.configStore = mTestConfigStore; |
| |
| isPrivateSpaceEnabled &= SdkLevel.isAtLeastS(); |
| if (isPrivateSpaceEnabled) { |
| mTestConfigStore.enablePrivateSpaceInPhotoPicker(); |
| mEnv.state.canForwardToProfileIdMap.put(TestProvidersAccess.USER_ID, true); |
| } |
| |
| mEnv.state.action = State.ACTION_BROWSE; |
| mEnv.state.acceptMimes = new String[]{"*/*"}; |
| |
| mQueryArgs.putString(DocumentsContract.QUERY_ARG_DISPLAY_NAME, SEARCH_STRING); |
| mLoader = new GlobalSearchLoader(mActivity, mEnv.providers, mEnv.state, |
| TestImmediateExecutor.createLookup(), new TestFileTypeLookup(), mQueryArgs, |
| TestProvidersAccess.USER_ID); |
| |
| final DocumentInfo doc = mEnv.model.createFile(SEARCH_STRING + ".jpg", FILE_FLAG); |
| doc.lastModified = System.currentTimeMillis(); |
| mEnv.mockProviders.get(TestProvidersAccess.DOWNLOADS.authority) |
| .setNextChildDocumentsReturns(doc); |
| |
| TestProvidersAccess.DOWNLOADS.flags |= DocumentsContract.Root.FLAG_SUPPORTS_SEARCH; |
| } |
| |
| @After |
| public void tearDown() { |
| TestProvidersAccess.DOWNLOADS.flags &= ~DocumentsContract.Root.FLAG_SUPPORTS_SEARCH; |
| } |
| |
| @Test |
| public void testNotSearchableRoot_beIgnored() { |
| TestProvidersAccess.PICKLES.flags |= DocumentsContract.Root.FLAG_LOCAL_ONLY; |
| assertTrue(mLoader.shouldIgnoreRoot(TestProvidersAccess.PICKLES)); |
| TestProvidersAccess.PICKLES.flags &= ~DocumentsContract.Root.FLAG_LOCAL_ONLY; |
| } |
| |
| @Test |
| public void testNotLocalOnlyRoot_beIgnored() { |
| if (isPrivateSpaceEnabled) return; |
| TestProvidersAccess.PICKLES.flags |= DocumentsContract.Root.FLAG_SUPPORTS_SEARCH; |
| assertTrue(mLoader.shouldIgnoreRoot(TestProvidersAccess.PICKLES)); |
| TestProvidersAccess.PICKLES.flags &= ~DocumentsContract.Root.FLAG_SUPPORTS_SEARCH; |
| } |
| |
| @Test |
| public void testShowAdvance_storageRoot_beIgnored() { |
| TestProvidersAccess.HOME.flags |= DocumentsContract.Root.FLAG_SUPPORTS_SEARCH; |
| assertTrue(mLoader.shouldIgnoreRoot(TestProvidersAccess.HOME)); |
| TestProvidersAccess.HOME.flags &= ~(DocumentsContract.Root.FLAG_SUPPORTS_SEARCH); |
| } |
| |
| @Test |
| public void testCrossProfileRoot_notInTextSearch_beIgnored() { |
| mEnv.state.supportsCrossProfile = true; |
| mQueryArgs.remove(DocumentsContract.QUERY_ARG_DISPLAY_NAME); |
| TestProvidersAccess.DOWNLOADS.userId = TestProvidersAccess.OtherUser.USER_ID; |
| assertThat(mLoader.shouldIgnoreRoot(TestProvidersAccess.DOWNLOADS)).isTrue(); |
| TestProvidersAccess.DOWNLOADS.userId = TestProvidersAccess.USER_ID; |
| } |
| |
| @Test |
| public void testCrossProfileRoot_inTextSearch_beIncluded() { |
| mEnv.state.supportsCrossProfile = true; |
| TestProvidersAccess.DOWNLOADS.userId = TestProvidersAccess.OtherUser.USER_ID; |
| assertThat(mLoader.shouldIgnoreRoot(TestProvidersAccess.DOWNLOADS)).isFalse(); |
| TestProvidersAccess.DOWNLOADS.userId = TestProvidersAccess.USER_ID; |
| } |
| |
| @Test |
| public void testSearchResult_includeDirectory() { |
| final DocumentInfo doc = mEnv.model.createFolder(SEARCH_STRING); |
| doc.lastModified = System.currentTimeMillis(); |
| |
| mEnv.mockProviders.get(TestProvidersAccess.DOWNLOADS.authority) |
| .setNextChildDocumentsReturns(doc); |
| |
| final DirectoryResult result = mLoader.loadInBackground(); |
| |
| final Cursor c = result.getCursor(); |
| assertEquals(1, c.getCount()); |
| |
| c.moveToNext(); |
| final String mimeType = c.getString(c.getColumnIndex(Document.COLUMN_MIME_TYPE)); |
| assertEquals(Document.MIME_TYPE_DIR, mimeType); |
| } |
| |
| @Test |
| public void testShowOrHideHiddenFiles() { |
| final DocumentInfo doc1 = mEnv.model.createFile(".test" + SEARCH_STRING); |
| final DocumentInfo doc2 = mEnv.model.createFile("test" + SEARCH_STRING); |
| doc1.documentId = ".test"; |
| doc2.documentId = "parent_folder/.hidden_folder/test"; |
| mEnv.mockProviders.get(TestProvidersAccess.DOWNLOADS.authority) |
| .setNextChildDocumentsReturns(doc1, doc2); |
| |
| assertEquals(false, mLoader.mState.showHiddenFiles); |
| DirectoryResult result = mLoader.loadInBackground(); |
| assertEquals(0, result.getCursor().getCount()); |
| |
| mLoader.mState.showHiddenFiles = true; |
| result = mLoader.loadInBackground(); |
| assertEquals(2, result.getCursor().getCount()); |
| } |
| |
| @Test |
| public void testSearchResult_isNotMovable() { |
| final DirectoryResult result = mLoader.loadInBackground(); |
| |
| final Cursor c = result.getCursor(); |
| assertEquals(1, c.getCount()); |
| |
| c.moveToNext(); |
| final int flags = c.getInt(c.getColumnIndex(Document.COLUMN_FLAGS)); |
| assertEquals(0, flags & Document.FLAG_SUPPORTS_DELETE); |
| assertEquals(0, flags & Document.FLAG_SUPPORTS_REMOVE); |
| assertEquals(0, flags & Document.FLAG_SUPPORTS_MOVE); |
| } |
| |
| @Test |
| public void testSearchResult_includeDirectory_excludedOtherUsers() { |
| mEnv.state.canShareAcrossProfile = false; |
| |
| TestProvidersAccess.DOWNLOADS.userId = TestProvidersAccess.USER_ID; |
| TestProvidersAccess.PICKLES.userId = TestProvidersAccess.OtherUser.USER_ID; |
| TestProvidersAccess.PICKLES.flags |= (DocumentsContract.Root.FLAG_SUPPORTS_SEARCH |
| | DocumentsContract.Root.FLAG_LOCAL_ONLY); |
| |
| final DocumentInfo currentUserDoc = mEnv.model.createFile( |
| SEARCH_STRING + "_currentUser.pdf"); |
| currentUserDoc.lastModified = System.currentTimeMillis(); |
| mEnv.mockProviders.get(TestProvidersAccess.DOWNLOADS.authority) |
| .setNextChildDocumentsReturns(currentUserDoc); |
| |
| final DocumentInfo otherUserDoc = mEnv.model.createFile(SEARCH_STRING + "_otherUser.png"); |
| otherUserDoc.lastModified = System.currentTimeMillis(); |
| mEnv.mockProviders.get(TestProvidersAccess.PICKLES.authority) |
| .setNextChildDocumentsReturns(otherUserDoc); |
| |
| final DirectoryResult result = mLoader.loadInBackground(); |
| final Cursor c = result.getCursor(); |
| |
| assertThat(c.getCount()).isEqualTo(1); |
| c.moveToNext(); |
| final String docName = c.getString(c.getColumnIndex(Document.COLUMN_DISPLAY_NAME)); |
| assertThat(docName).contains("currentUser"); |
| |
| TestProvidersAccess.DOWNLOADS.userId = TestProvidersAccess.USER_ID; |
| TestProvidersAccess.PICKLES.userId = TestProvidersAccess.USER_ID; |
| TestProvidersAccess.PICKLES.flags &= ~DocumentsContract.Root.FLAG_SUPPORTS_SEARCH; |
| } |
| |
| @Test |
| public void testSearchResult_includeSearchString() { |
| final DocumentInfo pdfDoc = mEnv.model.createFile(SEARCH_STRING + ".pdf"); |
| pdfDoc.lastModified = System.currentTimeMillis(); |
| |
| final DocumentInfo apkDoc = mEnv.model.createFile(SEARCH_STRING + ".apk"); |
| apkDoc.lastModified = System.currentTimeMillis(); |
| |
| final DocumentInfo testApkDoc = mEnv.model.createFile("test.apk"); |
| testApkDoc.lastModified = System.currentTimeMillis(); |
| |
| mEnv.mockProviders.get(TestProvidersAccess.DOWNLOADS.authority) |
| .setNextChildDocumentsReturns(pdfDoc, apkDoc, testApkDoc); |
| |
| mEnv.state.sortModel.sortByUser( |
| SortModel.SORT_DIMENSION_ID_TITLE, SortDimension.SORT_DIRECTION_ASCENDING); |
| |
| final DirectoryResult result = mLoader.loadInBackground(); |
| final Cursor c = result.getCursor(); |
| |
| assertEquals(2, c.getCount()); |
| |
| c.moveToNext(); |
| String displayName = c.getString(c.getColumnIndex(Document.COLUMN_DISPLAY_NAME)); |
| assertTrue(displayName.contains(SEARCH_STRING)); |
| |
| c.moveToNext(); |
| displayName = c.getString(c.getColumnIndex(Document.COLUMN_DISPLAY_NAME)); |
| assertTrue(displayName.contains(SEARCH_STRING)); |
| } |
| |
| @Test |
| public void testSearchResult_includeDifferentRoot() { |
| final DocumentInfo pdfDoc = mEnv.model.createFile(SEARCH_STRING + ".pdf"); |
| pdfDoc.lastModified = System.currentTimeMillis(); |
| |
| final DocumentInfo apkDoc = mEnv.model.createFile(SEARCH_STRING + ".apk"); |
| apkDoc.lastModified = System.currentTimeMillis(); |
| |
| final DocumentInfo testApkDoc = mEnv.model.createFile("test.apk"); |
| testApkDoc.lastModified = System.currentTimeMillis(); |
| |
| mEnv.mockProviders.get(TestProvidersAccess.PICKLES.authority) |
| .setNextChildDocumentsReturns(pdfDoc, apkDoc, testApkDoc); |
| |
| TestProvidersAccess.PICKLES.flags |= (DocumentsContract.Root.FLAG_SUPPORTS_SEARCH |
| | DocumentsContract.Root.FLAG_LOCAL_ONLY); |
| |
| mEnv.state.sortModel.sortByUser( |
| SortModel.SORT_DIMENSION_ID_TITLE, SortDimension.SORT_DIRECTION_ASCENDING); |
| |
| final DirectoryResult result = mLoader.loadInBackground(); |
| final Cursor c = result.getCursor(); |
| |
| assertEquals(3, c.getCount()); |
| |
| TestProvidersAccess.PICKLES.flags &= ~(DocumentsContract.Root.FLAG_SUPPORTS_SEARCH |
| | DocumentsContract.Root.FLAG_LOCAL_ONLY); |
| } |
| |
| @Test |
| public void testSearchResult_includeCurrentUserRootOnly() { |
| mEnv.state.canShareAcrossProfile = false; |
| mEnv.state.supportsCrossProfile = true; |
| |
| final DocumentInfo pdfDoc = mEnv.model.createFile(SEARCH_STRING + ".pdf"); |
| pdfDoc.lastModified = System.currentTimeMillis(); |
| |
| final DocumentInfo apkDoc = mEnv.model.createFile(SEARCH_STRING + ".apk"); |
| apkDoc.lastModified = System.currentTimeMillis(); |
| |
| final DocumentInfo testApkDoc = mEnv.model.createFile("test.apk"); |
| testApkDoc.lastModified = System.currentTimeMillis(); |
| |
| mEnv.mockProviders.get(TestProvidersAccess.PICKLES.authority) |
| .setNextChildDocumentsReturns(pdfDoc, apkDoc, testApkDoc); |
| TestProvidersAccess.PICKLES.userId = TestProvidersAccess.OtherUser.USER_ID; |
| |
| TestProvidersAccess.PICKLES.flags |= (DocumentsContract.Root.FLAG_SUPPORTS_SEARCH |
| | DocumentsContract.Root.FLAG_LOCAL_ONLY); |
| mEnv.state.sortModel.sortByUser( |
| SortModel.SORT_DIMENSION_ID_TITLE, SortDimension.SORT_DIRECTION_ASCENDING); |
| |
| final DirectoryResult result = mLoader.loadInBackground(); |
| final Cursor c = result.getCursor(); |
| |
| assertEquals(1, c.getCount()); |
| |
| TestProvidersAccess.PICKLES.userId = TestProvidersAccess.USER_ID; |
| TestProvidersAccess.PICKLES.flags &= ~(DocumentsContract.Root.FLAG_SUPPORTS_SEARCH |
| | DocumentsContract.Root.FLAG_LOCAL_ONLY); |
| } |
| |
| |
| @Test |
| public void testSearchResult_includeBothUsersRoots() { |
| if (isPrivateSpaceEnabled) { |
| mEnv.state.canForwardToProfileIdMap.put(TestProvidersAccess.OtherUser.USER_ID, true); |
| } else { |
| mEnv.state.canShareAcrossProfile = true; |
| } |
| mEnv.state.supportsCrossProfile = true; |
| |
| final DocumentInfo pdfDoc = mEnv.model.createFile(SEARCH_STRING + ".pdf"); |
| pdfDoc.lastModified = System.currentTimeMillis(); |
| |
| final DocumentInfo apkDoc = mEnv.model.createFile(SEARCH_STRING + ".apk"); |
| apkDoc.lastModified = System.currentTimeMillis(); |
| |
| final DocumentInfo testApkDoc = mEnv.model.createFile("test.apk"); |
| testApkDoc.lastModified = System.currentTimeMillis(); |
| |
| mEnv.mockProviders.get(TestProvidersAccess.PICKLES.authority) |
| .setNextChildDocumentsReturns(pdfDoc, apkDoc, testApkDoc); |
| TestProvidersAccess.PICKLES.userId = TestProvidersAccess.OtherUser.USER_ID; |
| |
| TestProvidersAccess.PICKLES.flags |= (DocumentsContract.Root.FLAG_SUPPORTS_SEARCH |
| | DocumentsContract.Root.FLAG_LOCAL_ONLY); |
| mEnv.state.sortModel.sortByUser( |
| SortModel.SORT_DIMENSION_ID_TITLE, SortDimension.SORT_DIRECTION_ASCENDING); |
| |
| final DirectoryResult result = mLoader.loadInBackground(); |
| final Cursor c = result.getCursor(); |
| |
| assertEquals(3, c.getCount()); |
| |
| TestProvidersAccess.PICKLES.userId = TestProvidersAccess.USER_ID; |
| TestProvidersAccess.PICKLES.flags &= ~(DocumentsContract.Root.FLAG_SUPPORTS_SEARCH |
| | DocumentsContract.Root.FLAG_LOCAL_ONLY); |
| } |
| |
| |
| @Test |
| public void testSearchResult_emptyCurrentUsersRoot() { |
| mEnv.state.canShareAcrossProfile = false; |
| mEnv.state.supportsCrossProfile = true; |
| |
| final DocumentInfo pdfDoc = mEnv.model.createFile(SEARCH_STRING + ".pdf"); |
| pdfDoc.lastModified = System.currentTimeMillis(); |
| |
| mEnv.mockProviders.get(TestProvidersAccess.PICKLES.authority) |
| .setNextChildDocumentsReturns(pdfDoc); |
| |
| TestProvidersAccess.DOWNLOADS.userId = TestProvidersAccess.OtherUser.USER_ID; |
| TestProvidersAccess.PICKLES.userId = TestProvidersAccess.OtherUser.USER_ID; |
| TestProvidersAccess.PICKLES.flags |= (DocumentsContract.Root.FLAG_SUPPORTS_SEARCH |
| | DocumentsContract.Root.FLAG_LOCAL_ONLY); |
| mEnv.state.sortModel.sortByUser( |
| SortModel.SORT_DIMENSION_ID_TITLE, SortDimension.SORT_DIRECTION_ASCENDING); |
| |
| final DirectoryResult result = mLoader.loadInBackground(); |
| assertThat(result.getCursor().getCount()).isEqualTo(0); |
| // We don't expect exception even if all roots are from other users. |
| assertThat(result.exception).isNull(); |
| |
| |
| TestProvidersAccess.DOWNLOADS.userId = TestProvidersAccess.USER_ID; |
| TestProvidersAccess.PICKLES.userId = TestProvidersAccess.USER_ID; |
| TestProvidersAccess.PICKLES.flags &= ~(DocumentsContract.Root.FLAG_SUPPORTS_SEARCH |
| | DocumentsContract.Root.FLAG_LOCAL_ONLY); |
| } |
| } |