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 package com.android.documentsui.testing; 17 18 import android.content.Context; 19 import android.provider.DocumentsContract.Document; 20 import android.test.mock.MockContentResolver; 21 22 import androidx.test.InstrumentationRegistry; 23 24 import com.android.documentsui.DocsSelectionHelper; 25 import com.android.documentsui.FocusManager; 26 import com.android.documentsui.Injector; 27 import com.android.documentsui.ModelId; 28 import com.android.documentsui.SelectionHelpers; 29 import com.android.documentsui.archives.ArchivesProvider; 30 import com.android.documentsui.base.DocumentInfo; 31 import com.android.documentsui.base.Features; 32 import com.android.documentsui.base.RootInfo; 33 import com.android.documentsui.base.State; 34 import com.android.documentsui.dirlist.TestFocusHandler; 35 import com.android.documentsui.sorting.SortModel; 36 import com.android.documentsui.ui.TestDialogController; 37 38 import java.util.ArrayList; 39 import java.util.HashMap; 40 import java.util.List; 41 import java.util.Map; 42 import java.util.concurrent.Executor; 43 44 public class TestEnv { 45 46 public static DocumentInfo FOLDER_0; 47 public static DocumentInfo FOLDER_1; 48 public static DocumentInfo FOLDER_2; 49 public static DocumentInfo FILE_TXT; 50 public static DocumentInfo FILE_PNG; 51 public static DocumentInfo FILE_JPG; 52 public static DocumentInfo FILE_GIF; 53 public static DocumentInfo FILE_PDF; 54 public static DocumentInfo FILE_MP4; 55 public static DocumentInfo FILE_APK; 56 public static DocumentInfo FILE_PARTIAL; 57 public static DocumentInfo FILE_ARCHIVE; 58 public static DocumentInfo FILE_IN_ARCHIVE; 59 public static DocumentInfo FILE_VIRTUAL; 60 public static DocumentInfo FILE_READ_ONLY; 61 62 public final TestScheduledExecutorService mExecutor; 63 public final State state = new State(); 64 public final TestProvidersAccess providers = new TestProvidersAccess(); 65 public final TestDocumentsAccess docs = new TestDocumentsAccess(); 66 public final TestFocusHandler focusHandler = new TestFocusHandler(); 67 public final TestDialogController dialogs = new TestDialogController(); 68 public final TestModel model; 69 public final TestModel archiveModel; 70 public final DocsSelectionHelper selectionMgr; 71 public final TestSearchViewManager searchViewManager; 72 public final Injector<?> injector; 73 public final Features features; 74 75 public final MockContentResolver contentResolver; 76 public final Map<String, TestDocumentsProvider> mockProviders; 77 TestEnv(Context context, Features features, String authority)78 private TestEnv(Context context, Features features, String authority) { 79 this.features = features; 80 state.sortModel = SortModel.createModel(); 81 mExecutor = new TestScheduledExecutorService(); 82 model = new TestModel(authority, features); 83 archiveModel = new TestModel(ArchivesProvider.AUTHORITY, features); 84 selectionMgr = SelectionHelpers.createTestInstance(); 85 searchViewManager = new TestSearchViewManager(); 86 injector = new Injector( 87 features, 88 new TestActivityConfig(), 89 null, // ScopedPreferences are not currently required for tests 90 null, // MessageBuilder is not currently required for tests 91 dialogs, 92 new TestFileTypeLookup(), 93 (roots) -> {}, // not sure why, but java gets angry when I declare roots type. 94 model); 95 96 injector.selectionMgr = selectionMgr; 97 injector.focusManager = new FocusManager(features, selectionMgr, null, null, 0); 98 injector.searchManager = searchViewManager; 99 100 contentResolver = new MockContentResolver(); 101 mockProviders = new HashMap<>(providers.getRootsBlocking().size()); 102 registerProviders(); 103 } 104 registerProviders()105 private void registerProviders() { 106 for (RootInfo root : providers.getRootsBlocking()) { 107 if (!mockProviders.containsKey(root.authority)) { 108 TestDocumentsProvider provider = new TestDocumentsProvider(root.authority); 109 contentResolver.addProvider(root.authority, provider); 110 mockProviders.put(root.authority, provider); 111 } 112 } 113 } 114 115 // Many terrible creational permutations == easy to user for test authors! create(Features features)116 public static TestEnv create(Features features) { 117 return create(features, TestProvidersAccess.HOME.authority); 118 } 119 create()120 public static TestEnv create() { 121 return create(TestProvidersAccess.HOME.authority); 122 } 123 create(Features features, String authority)124 public static TestEnv create(Features features, String authority) { 125 Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); 126 return create(context, features, authority); 127 } 128 create(String authority)129 public static TestEnv create(String authority) { 130 Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); 131 Features features = new Features.RuntimeFeatures(context.getResources(), null); 132 return create(context, features, authority); 133 } 134 create(Context context, Features features, String authority)135 private static TestEnv create(Context context, Features features, String authority) { 136 TestEnv env = new TestEnv(context, features, authority); 137 env.reset(); 138 return env; 139 } 140 clear()141 public void clear() { 142 model.reset(); 143 model.update(); 144 } 145 reset()146 public void reset() { 147 model.reset(); 148 FOLDER_0 = model.createFolder("folder 0"); 149 FOLDER_1 = model.createFolder("folder 1"); 150 FOLDER_2 = model.createFolder("folder 2"); 151 FILE_TXT = model.createFile("woowoo.txt"); 152 FILE_PNG = model.createFile("peppey.png"); 153 FILE_JPG = model.createFile("jiffy.jpg"); 154 FILE_GIF = model.createFile("glibby.gif"); 155 FILE_PDF = model.createFile("busy.pdf"); 156 FILE_MP4 = model.createFile("cameravideo.mp4"); 157 FILE_APK = model.createFile("becareful.apk"); 158 FILE_PARTIAL = model.createFile( 159 "UbuntuFlappyBird.iso", 160 Document.FLAG_SUPPORTS_DELETE 161 | Document.FLAG_PARTIAL); 162 FILE_READ_ONLY = model.createFile("topsecretsystemfile.bin", 0); 163 FILE_ARCHIVE = model.createFile("whatsinthere.zip"); 164 FILE_IN_ARCHIVE = archiveModel.createFile("whatsinthere.png", 0); 165 FILE_VIRTUAL = model.createDocument( 166 "virtualdoc.vnd", 167 "application/vnd.google-apps.document", 168 Document.FLAG_VIRTUAL_DOCUMENT 169 | Document.FLAG_SUPPORTS_DELETE 170 | Document.FLAG_SUPPORTS_RENAME); 171 172 archiveModel.update(); 173 model.update(); 174 } 175 populateStack()176 public void populateStack() { 177 DocumentInfo rootDoc = model.getDocument( 178 ModelId.build(TestProvidersAccess.HOME.authority, "1")); 179 180 // These are test setup sanity checks, not test assertions. 181 assert rootDoc != null; 182 assert rootDoc.isDirectory(); 183 assert FOLDER_0.equals(rootDoc); 184 185 state.stack.changeRoot(TestProvidersAccess.HOME); 186 state.stack.push(rootDoc); 187 } 188 beforeAsserts()189 public void beforeAsserts() throws Exception { 190 mExecutor.waitForTasks(30000); // 30 secs 191 } 192 lookupExecutor(String authority)193 public Executor lookupExecutor(String authority) { 194 return mExecutor; 195 } 196 selectDocument(DocumentInfo info)197 public void selectDocument(DocumentInfo info) { 198 List<String> ids = new ArrayList<>(1); 199 ids.add(ModelId.build(info.authority, info.documentId)); 200 selectionMgr.setItemsSelected(ids, true); 201 } 202 203 // Easily copy docs, so we don't pollute static data across tests. clone(DocumentInfo a)204 public static DocumentInfo clone(DocumentInfo a) { 205 DocumentInfo b = new DocumentInfo(); 206 b.authority = a.authority; 207 b.documentId = a.documentId; 208 b.mimeType = a.mimeType; 209 b.displayName = a.displayName; 210 b.lastModified = a.lastModified; 211 b.flags = a.flags; 212 b.summary = a.summary; 213 b.size = a.size; 214 b.icon = a.icon; 215 b.derivedUri = a.derivedUri; 216 217 return b; 218 } 219 } 220