DocumentLoaderTest.java revision 678ed36bebb7b0f5ff342e9da30d693bffb8aeb2
1/* 2 * Copyright (C) 2015 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 17package com.android.mtp; 18 19import android.content.Context; 20import android.database.Cursor; 21import android.mtp.MtpObjectInfo; 22import android.net.Uri; 23import android.provider.DocumentsContract; 24import android.test.AndroidTestCase; 25import android.test.suitebuilder.annotation.MediumTest; 26 27import java.io.IOException; 28import java.util.HashMap; 29import java.util.Map; 30import java.util.concurrent.CountDownLatch; 31 32@MediumTest 33public class DocumentLoaderTest extends AndroidTestCase { 34 private MtpDatabase mDatabase; 35 private BlockableTestMtpManager mManager; 36 private TestContentResolver mResolver; 37 private DocumentLoader mLoader; 38 final private Identifier mParentIdentifier = new Identifier( 39 0, 0, 0, "2", MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE); 40 41 @Override 42 public void setUp() throws Exception { 43 mDatabase = new MtpDatabase(getContext(), MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY); 44 45 mDatabase.getMapper().startAddingDocuments(null); 46 mDatabase.getMapper().putDeviceDocument( 47 new MtpDeviceRecord(0, "Device", null, true, new MtpRoot[0], null, null)); 48 mDatabase.getMapper().stopAddingDocuments(null); 49 50 mDatabase.getMapper().startAddingDocuments("1"); 51 mDatabase.getMapper().putStorageDocuments("1", new int[0], new MtpRoot[] { 52 new MtpRoot(0, 0, "Storage", 1000, 1000, "") 53 }); 54 mDatabase.getMapper().stopAddingDocuments("1"); 55 56 mManager = new BlockableTestMtpManager(getContext()); 57 mResolver = new TestContentResolver(); 58 } 59 60 @Override 61 public void tearDown() throws Exception { 62 mLoader.close(); 63 mDatabase.close(); 64 } 65 66 public void testBasic() throws Exception { 67 setUpLoader(); 68 69 final Uri uri = DocumentsContract.buildChildDocumentsUri( 70 MtpDocumentsProvider.AUTHORITY, mParentIdentifier.mDocumentId); 71 setUpDocument(mManager, 40); 72 mManager.blockDocument(0, 15); 73 mManager.blockDocument(0, 35); 74 75 { 76 final Cursor cursor = mLoader.queryChildDocuments( 77 MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION, mParentIdentifier); 78 assertEquals(DocumentLoader.NUM_INITIAL_ENTRIES, cursor.getCount()); 79 } 80 81 Thread.sleep(DocumentLoader.NOTIFY_PERIOD_MS); 82 mManager.unblockDocument(0, 15); 83 mResolver.waitForNotification(uri, 1); 84 85 { 86 final Cursor cursor = mLoader.queryChildDocuments( 87 MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION, mParentIdentifier); 88 assertEquals( 89 DocumentLoader.NUM_INITIAL_ENTRIES + DocumentLoader.NUM_LOADING_ENTRIES, 90 cursor.getCount()); 91 } 92 93 mManager.unblockDocument(0, 35); 94 mResolver.waitForNotification(uri, 2); 95 96 { 97 final Cursor cursor = mLoader.queryChildDocuments( 98 MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION, mParentIdentifier); 99 assertEquals(40, cursor.getCount()); 100 } 101 102 assertEquals(2, mResolver.getChangeCount(uri)); 103 } 104 105 public void testError_GetObjectHandles() throws Exception { 106 mManager = new BlockableTestMtpManager(getContext()) { 107 @Override 108 int[] getObjectHandles(int deviceId, int storageId, int parentObjectHandle) 109 throws IOException { 110 throw new IOException(); 111 } 112 }; 113 setUpLoader(); 114 mManager.setObjectHandles(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, null); 115 try { 116 try (final Cursor cursor = mLoader.queryChildDocuments( 117 MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION, mParentIdentifier)) {} 118 fail(); 119 } catch (IOException exception) { 120 // Expect exception. 121 } 122 } 123 124 public void testError_GetObjectInfo() throws Exception { 125 mManager = new BlockableTestMtpManager(getContext()) { 126 @Override 127 MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException { 128 if (objectHandle == DocumentLoader.NUM_INITIAL_ENTRIES) { 129 throw new IOException(); 130 } else { 131 return super.getObjectInfo(deviceId, objectHandle); 132 } 133 } 134 }; 135 setUpLoader(); 136 setUpDocument(mManager, DocumentLoader.NUM_INITIAL_ENTRIES); 137 try (final Cursor cursor = mLoader.queryChildDocuments( 138 MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION, mParentIdentifier)) { 139 // Even if MtpManager returns an error for a document, loading must complete. 140 assertFalse(cursor.getExtras().getBoolean(DocumentsContract.EXTRA_LOADING)); 141 } 142 } 143 144 private void setUpLoader() { 145 mLoader = new DocumentLoader( 146 new MtpDeviceRecord( 147 0, "Device", "Key", true, new MtpRoot[0], 148 TestUtil.OPERATIONS_SUPPORTED, new int[0]), 149 mManager, 150 mResolver, 151 mDatabase); 152 } 153 154 private void setUpDocument(TestMtpManager manager, int count) { 155 int[] childDocuments = new int[count]; 156 for (int i = 0; i < childDocuments.length; i++) { 157 final int objectHandle = i + 1; 158 childDocuments[i] = objectHandle; 159 manager.setObjectInfo(0, new MtpObjectInfo.Builder() 160 .setObjectHandle(objectHandle) 161 .setName(Integer.toString(i)) 162 .build()); 163 } 164 manager.setObjectHandles(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, childDocuments); 165 } 166 167 private static class BlockableTestMtpManager extends TestMtpManager { 168 final private Map<String, CountDownLatch> blockedDocuments = new HashMap<>(); 169 170 BlockableTestMtpManager(Context context) { 171 super(context); 172 } 173 174 void blockDocument(int deviceId, int objectHandle) { 175 blockedDocuments.put(pack(deviceId, objectHandle), new CountDownLatch(1)); 176 } 177 178 void unblockDocument(int deviceId, int objectHandle) { 179 blockedDocuments.get(pack(deviceId, objectHandle)).countDown(); 180 } 181 182 @Override 183 MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException { 184 final CountDownLatch latch = blockedDocuments.get(pack(deviceId, objectHandle)); 185 if (latch != null) { 186 try { 187 latch.await(); 188 } catch(InterruptedException e) { 189 fail(); 190 } 191 } 192 return super.getObjectInfo(deviceId, objectHandle); 193 } 194 } 195} 196