1 /* 2 * Copyright (C) 2018 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 com.google.common.truth.Truth.assertThat; 20 21 import static junit.framework.Assert.assertEquals; 22 import static junit.framework.Assert.assertTrue; 23 24 import android.database.Cursor; 25 import android.os.Bundle; 26 import android.provider.DocumentsContract; 27 import android.provider.DocumentsContract.Document; 28 29 import androidx.test.filters.MediumTest; 30 import androidx.test.runner.AndroidJUnit4; 31 32 import com.android.documentsui.base.DocumentInfo; 33 import com.android.documentsui.base.State; 34 import com.android.documentsui.sorting.SortDimension; 35 import com.android.documentsui.sorting.SortModel; 36 import com.android.documentsui.testing.ActivityManagers; 37 import com.android.documentsui.testing.TestEnv; 38 import com.android.documentsui.testing.TestFileTypeLookup; 39 import com.android.documentsui.testing.TestImmediateExecutor; 40 import com.android.documentsui.testing.TestProvidersAccess; 41 42 import org.junit.After; 43 import org.junit.Before; 44 import org.junit.Test; 45 import org.junit.runner.RunWith; 46 47 @RunWith(AndroidJUnit4.class) 48 @MediumTest 49 public class GlobalSearchLoaderTest { 50 51 private static final String SEARCH_STRING = "freddy"; 52 private static int FILE_FLAG = Document.FLAG_SUPPORTS_MOVE | Document.FLAG_SUPPORTS_DELETE 53 | Document.FLAG_SUPPORTS_REMOVE; 54 55 private TestEnv mEnv; 56 private TestActivity mActivity; 57 private GlobalSearchLoader mLoader; 58 private Bundle mQueryArgs = new Bundle(); 59 60 @Before setUp()61 public void setUp() { 62 mEnv = TestEnv.create(); 63 mActivity = TestActivity.create(mEnv); 64 mActivity.activityManager = ActivityManagers.create(false); 65 66 mEnv.state.action = State.ACTION_BROWSE; 67 mEnv.state.acceptMimes = new String[]{"*/*"}; 68 69 mQueryArgs.putString(DocumentsContract.QUERY_ARG_DISPLAY_NAME, SEARCH_STRING); 70 mLoader = new GlobalSearchLoader(mActivity, mEnv.providers, mEnv.state, 71 TestImmediateExecutor.createLookup(), new TestFileTypeLookup(), mQueryArgs, 72 TestProvidersAccess.USER_ID); 73 74 final DocumentInfo doc = mEnv.model.createFile(SEARCH_STRING + ".jpg", FILE_FLAG); 75 doc.lastModified = System.currentTimeMillis(); 76 mEnv.mockProviders.get(TestProvidersAccess.DOWNLOADS.authority) 77 .setNextChildDocumentsReturns(doc); 78 79 TestProvidersAccess.DOWNLOADS.flags |= DocumentsContract.Root.FLAG_SUPPORTS_SEARCH; 80 } 81 82 @After tearDown()83 public void tearDown() { 84 TestProvidersAccess.DOWNLOADS.flags &= ~DocumentsContract.Root.FLAG_SUPPORTS_SEARCH; 85 } 86 87 @Test testNotSearchableRoot_beIgnored()88 public void testNotSearchableRoot_beIgnored() { 89 TestProvidersAccess.PICKLES.flags |= DocumentsContract.Root.FLAG_LOCAL_ONLY; 90 assertTrue(mLoader.shouldIgnoreRoot(TestProvidersAccess.PICKLES)); 91 TestProvidersAccess.PICKLES.flags &= ~DocumentsContract.Root.FLAG_LOCAL_ONLY; 92 } 93 94 @Test testNotLocalOnlyRoot_beIgnored()95 public void testNotLocalOnlyRoot_beIgnored() { 96 TestProvidersAccess.PICKLES.flags |= DocumentsContract.Root.FLAG_SUPPORTS_SEARCH; 97 assertTrue(mLoader.shouldIgnoreRoot(TestProvidersAccess.PICKLES)); 98 TestProvidersAccess.PICKLES.flags &= ~DocumentsContract.Root.FLAG_SUPPORTS_SEARCH; 99 } 100 101 @Test testShowAdvance_storageRoot_beIgnored()102 public void testShowAdvance_storageRoot_beIgnored() { 103 TestProvidersAccess.HOME.flags |= DocumentsContract.Root.FLAG_SUPPORTS_SEARCH; 104 assertTrue(mLoader.shouldIgnoreRoot(TestProvidersAccess.HOME)); 105 TestProvidersAccess.HOME.flags &= ~(DocumentsContract.Root.FLAG_SUPPORTS_SEARCH); 106 } 107 108 @Test testCrossProfileRoot_notInTextSearch_beIgnored()109 public void testCrossProfileRoot_notInTextSearch_beIgnored() { 110 mEnv.state.supportsCrossProfile = true; 111 mQueryArgs.remove(DocumentsContract.QUERY_ARG_DISPLAY_NAME); 112 TestProvidersAccess.DOWNLOADS.userId = TestProvidersAccess.OtherUser.USER_ID; 113 assertThat(mLoader.shouldIgnoreRoot(TestProvidersAccess.DOWNLOADS)).isTrue(); 114 TestProvidersAccess.DOWNLOADS.userId = TestProvidersAccess.USER_ID; 115 } 116 117 @Test testCrossProfileRoot_inTextSearch_beIncluded()118 public void testCrossProfileRoot_inTextSearch_beIncluded() { 119 mEnv.state.supportsCrossProfile = true; 120 TestProvidersAccess.DOWNLOADS.userId = TestProvidersAccess.OtherUser.USER_ID; 121 assertThat(mLoader.shouldIgnoreRoot(TestProvidersAccess.DOWNLOADS)).isFalse(); 122 TestProvidersAccess.DOWNLOADS.userId = TestProvidersAccess.USER_ID; 123 } 124 125 @Test testSearchResult_includeDirectory()126 public void testSearchResult_includeDirectory() { 127 final DocumentInfo doc = mEnv.model.createFolder(SEARCH_STRING); 128 doc.lastModified = System.currentTimeMillis(); 129 130 mEnv.mockProviders.get(TestProvidersAccess.DOWNLOADS.authority) 131 .setNextChildDocumentsReturns(doc); 132 133 final DirectoryResult result = mLoader.loadInBackground(); 134 135 final Cursor c = result.getCursor(); 136 assertEquals(1, c.getCount()); 137 138 c.moveToNext(); 139 final String mimeType = c.getString(c.getColumnIndex(Document.COLUMN_MIME_TYPE)); 140 assertEquals(Document.MIME_TYPE_DIR, mimeType); 141 } 142 143 @Test testShowOrHideHiddenFiles()144 public void testShowOrHideHiddenFiles() { 145 final DocumentInfo doc1 = mEnv.model.createFile(".test" + SEARCH_STRING); 146 final DocumentInfo doc2 = mEnv.model.createFile("test" + SEARCH_STRING); 147 doc1.documentId = ".test"; 148 doc2.documentId = "parent_folder/.hidden_folder/test"; 149 mEnv.mockProviders.get(TestProvidersAccess.DOWNLOADS.authority) 150 .setNextChildDocumentsReturns(doc1, doc2); 151 152 assertEquals(false, mLoader.mState.showHiddenFiles); 153 DirectoryResult result = mLoader.loadInBackground(); 154 assertEquals(0, result.getCursor().getCount()); 155 156 mLoader.mState.showHiddenFiles = true; 157 result = mLoader.loadInBackground(); 158 assertEquals(2, result.getCursor().getCount()); 159 } 160 161 @Test testSearchResult_isNotMovable()162 public void testSearchResult_isNotMovable() { 163 final DirectoryResult result = mLoader.loadInBackground(); 164 165 final Cursor c = result.getCursor(); 166 assertEquals(1, c.getCount()); 167 168 c.moveToNext(); 169 final int flags = c.getInt(c.getColumnIndex(Document.COLUMN_FLAGS)); 170 assertEquals(0, flags & Document.FLAG_SUPPORTS_DELETE); 171 assertEquals(0, flags & Document.FLAG_SUPPORTS_REMOVE); 172 assertEquals(0, flags & Document.FLAG_SUPPORTS_MOVE); 173 } 174 175 @Test testSearchResult_includeDirectory_excludedOtherUsers()176 public void testSearchResult_includeDirectory_excludedOtherUsers() { 177 mEnv.state.canShareAcrossProfile = false; 178 179 TestProvidersAccess.DOWNLOADS.userId = TestProvidersAccess.USER_ID; 180 TestProvidersAccess.PICKLES.userId = TestProvidersAccess.OtherUser.USER_ID; 181 TestProvidersAccess.PICKLES.flags |= (DocumentsContract.Root.FLAG_SUPPORTS_SEARCH 182 | DocumentsContract.Root.FLAG_LOCAL_ONLY); 183 184 final DocumentInfo currentUserDoc = mEnv.model.createFile( 185 SEARCH_STRING + "_currentUser.pdf"); 186 currentUserDoc.lastModified = System.currentTimeMillis(); 187 mEnv.mockProviders.get(TestProvidersAccess.DOWNLOADS.authority) 188 .setNextChildDocumentsReturns(currentUserDoc); 189 190 final DocumentInfo otherUserDoc = mEnv.model.createFile(SEARCH_STRING + "_otherUser.png"); 191 otherUserDoc.lastModified = System.currentTimeMillis(); 192 mEnv.mockProviders.get(TestProvidersAccess.PICKLES.authority) 193 .setNextChildDocumentsReturns(otherUserDoc); 194 195 final DirectoryResult result = mLoader.loadInBackground(); 196 final Cursor c = result.getCursor(); 197 198 assertThat(c.getCount()).isEqualTo(1); 199 c.moveToNext(); 200 final String docName = c.getString(c.getColumnIndex(Document.COLUMN_DISPLAY_NAME)); 201 assertThat(docName).contains("currentUser"); 202 203 TestProvidersAccess.DOWNLOADS.userId = TestProvidersAccess.USER_ID; 204 TestProvidersAccess.PICKLES.userId = TestProvidersAccess.USER_ID; 205 TestProvidersAccess.PICKLES.flags &= ~DocumentsContract.Root.FLAG_SUPPORTS_SEARCH; 206 } 207 208 @Test testSearchResult_includeSearchString()209 public void testSearchResult_includeSearchString() { 210 final DocumentInfo pdfDoc = mEnv.model.createFile(SEARCH_STRING + ".pdf"); 211 pdfDoc.lastModified = System.currentTimeMillis(); 212 213 final DocumentInfo apkDoc = mEnv.model.createFile(SEARCH_STRING + ".apk"); 214 apkDoc.lastModified = System.currentTimeMillis(); 215 216 final DocumentInfo testApkDoc = mEnv.model.createFile("test.apk"); 217 testApkDoc.lastModified = System.currentTimeMillis(); 218 219 mEnv.mockProviders.get(TestProvidersAccess.DOWNLOADS.authority) 220 .setNextChildDocumentsReturns(pdfDoc, apkDoc, testApkDoc); 221 222 mEnv.state.sortModel.sortByUser( 223 SortModel.SORT_DIMENSION_ID_TITLE, SortDimension.SORT_DIRECTION_ASCENDING); 224 225 final DirectoryResult result = mLoader.loadInBackground(); 226 final Cursor c = result.getCursor(); 227 228 assertEquals(2, c.getCount()); 229 230 c.moveToNext(); 231 String displayName = c.getString(c.getColumnIndex(Document.COLUMN_DISPLAY_NAME)); 232 assertTrue(displayName.contains(SEARCH_STRING)); 233 234 c.moveToNext(); 235 displayName = c.getString(c.getColumnIndex(Document.COLUMN_DISPLAY_NAME)); 236 assertTrue(displayName.contains(SEARCH_STRING)); 237 } 238 239 @Test testSearchResult_includeDifferentRoot()240 public void testSearchResult_includeDifferentRoot() { 241 final DocumentInfo pdfDoc = mEnv.model.createFile(SEARCH_STRING + ".pdf"); 242 pdfDoc.lastModified = System.currentTimeMillis(); 243 244 final DocumentInfo apkDoc = mEnv.model.createFile(SEARCH_STRING + ".apk"); 245 apkDoc.lastModified = System.currentTimeMillis(); 246 247 final DocumentInfo testApkDoc = mEnv.model.createFile("test.apk"); 248 testApkDoc.lastModified = System.currentTimeMillis(); 249 250 mEnv.mockProviders.get(TestProvidersAccess.PICKLES.authority) 251 .setNextChildDocumentsReturns(pdfDoc, apkDoc, testApkDoc); 252 253 TestProvidersAccess.PICKLES.flags |= (DocumentsContract.Root.FLAG_SUPPORTS_SEARCH 254 | DocumentsContract.Root.FLAG_LOCAL_ONLY); 255 256 mEnv.state.sortModel.sortByUser( 257 SortModel.SORT_DIMENSION_ID_TITLE, SortDimension.SORT_DIRECTION_ASCENDING); 258 259 final DirectoryResult result = mLoader.loadInBackground(); 260 final Cursor c = result.getCursor(); 261 262 assertEquals(3, c.getCount()); 263 264 TestProvidersAccess.PICKLES.flags &= ~(DocumentsContract.Root.FLAG_SUPPORTS_SEARCH 265 | DocumentsContract.Root.FLAG_LOCAL_ONLY); 266 } 267 268 @Test testSearchResult_includeCurrentUserRootOnly()269 public void testSearchResult_includeCurrentUserRootOnly() { 270 mEnv.state.canShareAcrossProfile = false; 271 mEnv.state.supportsCrossProfile = true; 272 273 final DocumentInfo pdfDoc = mEnv.model.createFile(SEARCH_STRING + ".pdf"); 274 pdfDoc.lastModified = System.currentTimeMillis(); 275 276 final DocumentInfo apkDoc = mEnv.model.createFile(SEARCH_STRING + ".apk"); 277 apkDoc.lastModified = System.currentTimeMillis(); 278 279 final DocumentInfo testApkDoc = mEnv.model.createFile("test.apk"); 280 testApkDoc.lastModified = System.currentTimeMillis(); 281 282 mEnv.mockProviders.get(TestProvidersAccess.PICKLES.authority) 283 .setNextChildDocumentsReturns(pdfDoc, apkDoc, testApkDoc); 284 TestProvidersAccess.PICKLES.userId = TestProvidersAccess.OtherUser.USER_ID; 285 286 TestProvidersAccess.PICKLES.flags |= (DocumentsContract.Root.FLAG_SUPPORTS_SEARCH 287 | DocumentsContract.Root.FLAG_LOCAL_ONLY); 288 mEnv.state.sortModel.sortByUser( 289 SortModel.SORT_DIMENSION_ID_TITLE, SortDimension.SORT_DIRECTION_ASCENDING); 290 291 final DirectoryResult result = mLoader.loadInBackground(); 292 final Cursor c = result.getCursor(); 293 294 assertEquals(1, c.getCount()); 295 296 TestProvidersAccess.PICKLES.userId = TestProvidersAccess.USER_ID; 297 TestProvidersAccess.PICKLES.flags &= ~(DocumentsContract.Root.FLAG_SUPPORTS_SEARCH 298 | DocumentsContract.Root.FLAG_LOCAL_ONLY); 299 } 300 301 302 @Test testSearchResult_includeBothUsersRoots()303 public void testSearchResult_includeBothUsersRoots() { 304 mEnv.state.canShareAcrossProfile = true; 305 mEnv.state.supportsCrossProfile = true; 306 307 final DocumentInfo pdfDoc = mEnv.model.createFile(SEARCH_STRING + ".pdf"); 308 pdfDoc.lastModified = System.currentTimeMillis(); 309 310 final DocumentInfo apkDoc = mEnv.model.createFile(SEARCH_STRING + ".apk"); 311 apkDoc.lastModified = System.currentTimeMillis(); 312 313 final DocumentInfo testApkDoc = mEnv.model.createFile("test.apk"); 314 testApkDoc.lastModified = System.currentTimeMillis(); 315 316 mEnv.mockProviders.get(TestProvidersAccess.PICKLES.authority) 317 .setNextChildDocumentsReturns(pdfDoc, apkDoc, testApkDoc); 318 TestProvidersAccess.PICKLES.userId = TestProvidersAccess.OtherUser.USER_ID; 319 320 TestProvidersAccess.PICKLES.flags |= (DocumentsContract.Root.FLAG_SUPPORTS_SEARCH 321 | DocumentsContract.Root.FLAG_LOCAL_ONLY); 322 mEnv.state.sortModel.sortByUser( 323 SortModel.SORT_DIMENSION_ID_TITLE, SortDimension.SORT_DIRECTION_ASCENDING); 324 325 final DirectoryResult result = mLoader.loadInBackground(); 326 final Cursor c = result.getCursor(); 327 328 assertEquals(3, c.getCount()); 329 330 TestProvidersAccess.PICKLES.userId = TestProvidersAccess.USER_ID; 331 TestProvidersAccess.PICKLES.flags &= ~(DocumentsContract.Root.FLAG_SUPPORTS_SEARCH 332 | DocumentsContract.Root.FLAG_LOCAL_ONLY); 333 } 334 335 336 @Test testSearchResult_emptyCurrentUsersRoot()337 public void testSearchResult_emptyCurrentUsersRoot() { 338 mEnv.state.canShareAcrossProfile = false; 339 mEnv.state.supportsCrossProfile = true; 340 341 final DocumentInfo pdfDoc = mEnv.model.createFile(SEARCH_STRING + ".pdf"); 342 pdfDoc.lastModified = System.currentTimeMillis(); 343 344 mEnv.mockProviders.get(TestProvidersAccess.PICKLES.authority) 345 .setNextChildDocumentsReturns(pdfDoc); 346 347 TestProvidersAccess.DOWNLOADS.userId = TestProvidersAccess.OtherUser.USER_ID; 348 TestProvidersAccess.PICKLES.userId = TestProvidersAccess.OtherUser.USER_ID; 349 TestProvidersAccess.PICKLES.flags |= (DocumentsContract.Root.FLAG_SUPPORTS_SEARCH 350 | DocumentsContract.Root.FLAG_LOCAL_ONLY); 351 mEnv.state.sortModel.sortByUser( 352 SortModel.SORT_DIMENSION_ID_TITLE, SortDimension.SORT_DIRECTION_ASCENDING); 353 354 final DirectoryResult result = mLoader.loadInBackground(); 355 assertThat(result.getCursor().getCount()).isEqualTo(0); 356 // We don't expect exception even if all roots are from other users. 357 assertThat(result.exception).isNull(); 358 359 360 TestProvidersAccess.DOWNLOADS.userId = TestProvidersAccess.USER_ID; 361 TestProvidersAccess.PICKLES.userId = TestProvidersAccess.USER_ID; 362 TestProvidersAccess.PICKLES.flags &= ~(DocumentsContract.Root.FLAG_SUPPORTS_SEARCH 363 | DocumentsContract.Root.FLAG_LOCAL_ONLY); 364 } 365 } 366