1 /* 2 * Copyright (C) 2017 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.assertFalse; 23 import static junit.framework.Assert.assertTrue; 24 25 import static org.mockito.ArgumentMatchers.any; 26 import static org.mockito.Mockito.when; 27 28 import android.database.Cursor; 29 import android.provider.DocumentsContract.Document; 30 31 import androidx.test.filters.MediumTest; 32 33 import com.android.documentsui.base.DocumentInfo; 34 import com.android.documentsui.base.State; 35 import com.android.documentsui.base.UserId; 36 import com.android.documentsui.testing.ActivityManagers; 37 import com.android.documentsui.testing.TestCursor; 38 import com.android.documentsui.testing.TestEnv; 39 import com.android.documentsui.testing.TestFileTypeLookup; 40 import com.android.documentsui.testing.TestImmediateExecutor; 41 import com.android.documentsui.testing.TestProvidersAccess; 42 import com.android.documentsui.testing.UserManagers; 43 import com.android.modules.utils.build.SdkLevel; 44 45 import com.google.common.collect.Lists; 46 47 import org.junit.Before; 48 import org.junit.Test; 49 import org.junit.runner.RunWith; 50 import org.junit.runners.Parameterized; 51 import org.junit.runners.Parameterized.Parameter; 52 import org.junit.runners.Parameterized.Parameters; 53 54 import java.util.concurrent.CountDownLatch; 55 import java.util.concurrent.TimeUnit; 56 57 @RunWith(Parameterized.class) 58 @MediumTest 59 public class RecentsLoaderTests { 60 61 private TestEnv mEnv; 62 private TestActivity mActivity; 63 private RecentsLoader mLoader; 64 private TestConfigStore mTestConfigStore; 65 66 @Parameter(0) 67 public boolean isPrivateSpaceEnabled; 68 69 /** 70 * Parameterized test to run all the tests in this class twice, once with private space enabled 71 * and once with private space disabled. 72 */ 73 @Parameters(name = "privateSpaceEnabled={0}") data()74 public static Iterable<?> data() { 75 return Lists.newArrayList(true, false); 76 } 77 78 @Before setUp()79 public void setUp() { 80 mEnv = TestEnv.create(); 81 mActivity = TestActivity.create(mEnv); 82 mActivity.activityManager = ActivityManagers.create(false); 83 mActivity.userManager = UserManagers.create(); 84 mTestConfigStore = new TestConfigStore(); 85 mEnv.state.configStore = mTestConfigStore; 86 87 mEnv.state.action = State.ACTION_BROWSE; 88 mEnv.state.acceptMimes = new String[]{"*/*"}; 89 isPrivateSpaceEnabled = SdkLevel.isAtLeastS() && isPrivateSpaceEnabled; 90 if (isPrivateSpaceEnabled) { 91 mTestConfigStore.enablePrivateSpaceInPhotoPicker(); 92 mEnv.state.canForwardToProfileIdMap.put(UserId.DEFAULT_USER, true); 93 mEnv.state.canForwardToProfileIdMap.put(TestProvidersAccess.OtherUser.USER_ID, true); 94 } else { 95 mEnv.state.canShareAcrossProfile = true; 96 } 97 98 mLoader = new RecentsLoader(mActivity, mEnv.providers, mEnv.state, 99 TestImmediateExecutor.createLookup(), new TestFileTypeLookup(), 100 TestProvidersAccess.USER_ID); 101 } 102 103 @Test testNotLocalOnlyRoot_beIgnored()104 public void testNotLocalOnlyRoot_beIgnored() { 105 assertTrue(mLoader.shouldIgnoreRoot(TestProvidersAccess.PICKLES)); 106 } 107 108 @Test testLocalOnlyRoot_supportRecent_notIgnored()109 public void testLocalOnlyRoot_supportRecent_notIgnored() { 110 assertFalse(mLoader.shouldIgnoreRoot(TestProvidersAccess.DOWNLOADS)); 111 } 112 113 @Test testLocalOnlyRoot_supportRecent_differentUser_beIgnored()114 public void testLocalOnlyRoot_supportRecent_differentUser_beIgnored() { 115 assertTrue(mLoader.shouldIgnoreRoot(TestProvidersAccess.OtherUser.DOWNLOADS)); 116 } 117 118 @Test testDocumentsNotIncludeDirectory()119 public void testDocumentsNotIncludeDirectory() { 120 final DocumentInfo doc = mEnv.model.createFolder("test"); 121 doc.lastModified = System.currentTimeMillis(); 122 123 mEnv.mockProviders.get(TestProvidersAccess.HOME.authority) 124 .setNextChildDocumentsReturns(doc); 125 126 final DirectoryResult result = mLoader.loadInBackground(); 127 128 final Cursor c = result.getCursor(); 129 assertEquals(0, c.getCount()); 130 } 131 132 @Test testShowOrHideHiddenFiles()133 public void testShowOrHideHiddenFiles() { 134 final DocumentInfo doc1 = mEnv.model.createFile(".test"); 135 final DocumentInfo doc2 = mEnv.model.createFile("test"); 136 doc1.documentId = ".test"; 137 doc2.documentId = "parent_folder/.hidden_folder/test"; 138 doc1.lastModified = System.currentTimeMillis(); 139 doc2.lastModified = System.currentTimeMillis(); 140 mEnv.mockProviders.get(TestProvidersAccess.HOME.authority) 141 .setNextRecentDocumentsReturns(doc1, doc2); 142 143 assertFalse(mLoader.mState.showHiddenFiles); 144 DirectoryResult result = mLoader.loadInBackground(); 145 assertEquals(0, result.getCursor().getCount()); 146 147 mLoader.mState.showHiddenFiles = true; 148 result = mLoader.loadInBackground(); 149 assertEquals(2, result.getCursor().getCount()); 150 } 151 152 @Test testDocumentsNotMovable()153 public void testDocumentsNotMovable() { 154 final DocumentInfo doc = mEnv.model.createFile("freddy.jpg", 155 Document.FLAG_SUPPORTS_MOVE 156 | Document.FLAG_SUPPORTS_DELETE 157 | Document.FLAG_SUPPORTS_REMOVE); 158 doc.lastModified = System.currentTimeMillis(); 159 mEnv.mockProviders.get(TestProvidersAccess.HOME.authority) 160 .setNextRecentDocumentsReturns(doc); 161 162 final DirectoryResult result = mLoader.loadInBackground(); 163 164 final Cursor c = result.getCursor(); 165 assertEquals(1, c.getCount()); 166 for (int i = 0; i < c.getCount(); ++i) { 167 c.moveToNext(); 168 final int flags = c.getInt(c.getColumnIndex(Document.COLUMN_FLAGS)); 169 assertEquals(0, flags & Document.FLAG_SUPPORTS_DELETE); 170 assertEquals(0, flags & Document.FLAG_SUPPORTS_REMOVE); 171 assertEquals(0, flags & Document.FLAG_SUPPORTS_MOVE); 172 } 173 } 174 175 @Test testContentsUpdate_observable()176 public void testContentsUpdate_observable() throws Exception { 177 final CountDownLatch latch = new CountDownLatch(1); 178 179 // Please be mindful of the fact that the callback will be invoked on the Main (aka UI) 180 // thread, while the test itself is running on another (dedicated) thread. 181 final Runnable onContentChangedCallback = latch::countDown; 182 mLoader.setObserver(new LockingContentObserver( 183 new ContentLock(), onContentChangedCallback)); 184 185 final DocumentInfo doc = mEnv.model.createFile("freddy.jpg"); 186 doc.lastModified = System.currentTimeMillis(); 187 mEnv.mockProviders.get(TestProvidersAccess.HOME.authority) 188 .setNextRecentDocumentsReturns(doc); 189 190 mLoader.loadInBackground(); 191 192 final TestCursor c = (TestCursor) mEnv.mockProviders.get(TestProvidersAccess.HOME.authority) 193 .queryRecentDocuments(null, null); 194 c.mockOnChange(); 195 196 final boolean onContentChangedCallbackInvoked = latch.await(1, TimeUnit.SECONDS); 197 assertTrue(onContentChangedCallbackInvoked); 198 } 199 200 @Test testLoaderOnUserWithoutPermission()201 public void testLoaderOnUserWithoutPermission() { 202 if (isPrivateSpaceEnabled) { 203 mEnv.state.canForwardToProfileIdMap.put(TestProvidersAccess.OtherUser.USER_ID, false); 204 } else { 205 mEnv.state.canShareAcrossProfile = false; 206 } 207 mLoader = new RecentsLoader(mActivity, mEnv.providers, mEnv.state, 208 TestImmediateExecutor.createLookup(), new TestFileTypeLookup(), 209 TestProvidersAccess.OtherUser.USER_ID); 210 final DirectoryResult result = mLoader.loadInBackground(); 211 212 assertThat(result.getCursor()).isNull(); 213 assertThat(result.exception).isInstanceOf(CrossProfileNoPermissionException.class); 214 } 215 216 @Test testLoaderOnUser_quietMode()217 public void testLoaderOnUser_quietMode() { 218 when(mActivity.userManager.isQuietModeEnabled(any())).thenReturn(true); 219 final DirectoryResult result = mLoader.loadInBackground(); 220 221 assertThat(result.getCursor()).isNull(); 222 assertThat(result.exception).isInstanceOf(CrossProfileQuietModeException.class); 223 } 224 } 225