• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.documentsui.archives;
18 
19 import com.android.documentsui.archives.ReadableArchive;
20 import com.android.documentsui.tests.R;
21 
22 import android.content.Context;
23 import android.database.Cursor;
24 import android.net.Uri;
25 import android.os.ParcelFileDescriptor;
26 import android.provider.DocumentsContract.Document;
27 import android.support.test.InstrumentationRegistry;
28 import android.system.ErrnoException;
29 import android.system.Os;
30 import android.system.OsConstants;
31 import android.test.AndroidTestCase;
32 import android.test.suitebuilder.annotation.MediumTest;
33 
34 import java.io.File;
35 import java.io.FileOutputStream;
36 import java.io.IOException;
37 import java.io.InputStream;
38 import java.util.Scanner;
39 import java.util.concurrent.ExecutorService;
40 import java.util.concurrent.Executors;
41 import java.util.concurrent.TimeUnit;
42 
43 @MediumTest
44 public class ReadableArchiveTest extends AndroidTestCase {
45     private static final Uri ARCHIVE_URI = Uri.parse("content://i/love/strawberries");
46     private static final String NOTIFICATION_URI =
47             "content://com.android.documentsui.archives/notification-uri";
48     private ExecutorService mExecutor = null;
49     private Archive mArchive = null;
50     private TestUtils mTestUtils = null;
51 
52     @Override
setUp()53     public void setUp() throws Exception {
54         super.setUp();
55         mExecutor = Executors.newSingleThreadExecutor();
56         mTestUtils = new TestUtils(InstrumentationRegistry.getTargetContext(),
57                 InstrumentationRegistry.getContext(), mExecutor);
58     }
59 
60     @Override
tearDown()61     public void tearDown() throws Exception {
62         mExecutor.shutdown();
63         assertTrue(mExecutor.awaitTermination(3 /* timeout */, TimeUnit.SECONDS));
64         if (mArchive != null) {
65             mArchive.close();
66         }
67         super.tearDown();
68     }
69 
createArchiveId(String path)70     public static ArchiveId createArchiveId(String path) {
71         return new ArchiveId(ARCHIVE_URI, ParcelFileDescriptor.MODE_READ_ONLY, path);
72     }
73 
loadArchive(ParcelFileDescriptor descriptor)74     public void loadArchive(ParcelFileDescriptor descriptor) throws IOException {
75         mArchive = ReadableArchive.createForParcelFileDescriptor(
76                 InstrumentationRegistry.getTargetContext(),
77                 descriptor,
78                 ARCHIVE_URI,
79                 ParcelFileDescriptor.MODE_READ_ONLY,
80                 Uri.parse(NOTIFICATION_URI));
81     }
82 
testQueryChildDocument()83     public void testQueryChildDocument() throws IOException {
84         loadArchive(mTestUtils.getNonSeekableDescriptor(R.raw.archive));
85         final Cursor cursor = mArchive.queryChildDocuments(
86                 createArchiveId("/").toDocumentId(), null, null);
87 
88         assertTrue(cursor.moveToFirst());
89         assertEquals(
90                 createArchiveId("/file1.txt").toDocumentId(),
91                 cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DOCUMENT_ID)));
92         assertEquals("file1.txt",
93                 cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DISPLAY_NAME)));
94         assertEquals("text/plain",
95                 cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE)));
96         assertEquals(13,
97                 cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
98 
99         assertTrue(cursor.moveToNext());
100         assertEquals(createArchiveId("/dir1/").toDocumentId(),
101                 cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DOCUMENT_ID)));
102         assertEquals("dir1",
103                 cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DISPLAY_NAME)));
104         assertEquals(Document.MIME_TYPE_DIR,
105                 cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE)));
106         assertEquals(0,
107                 cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
108 
109         assertTrue(cursor.moveToNext());
110         assertEquals(
111                 createArchiveId("/dir2/").toDocumentId(),
112                 cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DOCUMENT_ID)));
113         assertEquals("dir2",
114                 cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DISPLAY_NAME)));
115         assertEquals(Document.MIME_TYPE_DIR,
116                 cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE)));
117         assertEquals(0,
118                 cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
119 
120         assertFalse(cursor.moveToNext());
121 
122         // Check if querying children works too.
123         final Cursor childCursor = mArchive.queryChildDocuments(
124                 createArchiveId("/dir1/").toDocumentId(), null, null);
125 
126         assertTrue(childCursor.moveToFirst());
127         assertEquals(
128                 createArchiveId("/dir1/cherries.txt").toDocumentId(),
129                 childCursor.getString(childCursor.getColumnIndexOrThrow(
130                         Document.COLUMN_DOCUMENT_ID)));
131         assertEquals("cherries.txt",
132                 childCursor.getString(childCursor.getColumnIndexOrThrow(
133                         Document.COLUMN_DISPLAY_NAME)));
134         assertEquals("text/plain",
135                 childCursor.getString(childCursor.getColumnIndexOrThrow(
136                         Document.COLUMN_MIME_TYPE)));
137         assertEquals(17,
138                 childCursor.getInt(childCursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
139     }
140 
testQueryChildDocument_NoDirs()141     public void testQueryChildDocument_NoDirs() throws IOException {
142         loadArchive(mTestUtils.getNonSeekableDescriptor(R.raw.no_dirs));
143         final Cursor cursor = mArchive.queryChildDocuments(
144             createArchiveId("/").toDocumentId(), null, null);
145 
146         assertTrue(cursor.moveToFirst());
147         assertEquals(
148                 createArchiveId("/dir1/").toDocumentId(),
149                 cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DOCUMENT_ID)));
150         assertEquals("dir1",
151                 cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DISPLAY_NAME)));
152         assertEquals(Document.MIME_TYPE_DIR,
153                 cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE)));
154         assertEquals(0,
155                 cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
156         assertFalse(cursor.moveToNext());
157 
158         final Cursor childCursor = mArchive.queryChildDocuments(
159                 createArchiveId("/dir1/").toDocumentId(), null, null);
160 
161         assertTrue(childCursor.moveToFirst());
162         assertEquals(
163                 createArchiveId("/dir1/dir2/").toDocumentId(),
164                 childCursor.getString(childCursor.getColumnIndexOrThrow(
165                         Document.COLUMN_DOCUMENT_ID)));
166         assertEquals("dir2",
167                 childCursor.getString(childCursor.getColumnIndexOrThrow(
168                         Document.COLUMN_DISPLAY_NAME)));
169         assertEquals(Document.MIME_TYPE_DIR,
170                 childCursor.getString(childCursor.getColumnIndexOrThrow(
171                         Document.COLUMN_MIME_TYPE)));
172         assertEquals(0,
173                 childCursor.getInt(childCursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
174         assertFalse(childCursor.moveToNext());
175 
176         final Cursor childCursor2 = mArchive.queryChildDocuments(
177                 createArchiveId("/dir1/dir2/").toDocumentId(),
178                 null, null);
179 
180         assertTrue(childCursor2.moveToFirst());
181         assertEquals(
182                 createArchiveId("/dir1/dir2/cherries.txt").toDocumentId(),
183                 childCursor2.getString(childCursor.getColumnIndexOrThrow(
184                         Document.COLUMN_DOCUMENT_ID)));
185         assertFalse(childCursor2.moveToNext());
186     }
187 
testQueryChildDocument_EmptyDirs()188     public void testQueryChildDocument_EmptyDirs() throws IOException {
189         loadArchive(mTestUtils.getNonSeekableDescriptor(R.raw.empty_dirs));
190         final Cursor cursor = mArchive.queryChildDocuments(
191                 createArchiveId("/").toDocumentId(), null, null);
192 
193         assertTrue(cursor.moveToFirst());
194         assertEquals(
195                 createArchiveId("/dir1/").toDocumentId(),
196                 cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DOCUMENT_ID)));
197         assertEquals("dir1",
198                 cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DISPLAY_NAME)));
199         assertEquals(Document.MIME_TYPE_DIR,
200                 cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE)));
201         assertEquals(0,
202                 cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
203         assertFalse(cursor.moveToNext());
204 
205         final Cursor childCursor = mArchive.queryChildDocuments(
206                 createArchiveId("/dir1/").toDocumentId(), null, null);
207 
208         assertTrue(childCursor.moveToFirst());
209         assertEquals(
210                 createArchiveId("/dir1/dir2/").toDocumentId(),
211                 childCursor.getString(childCursor.getColumnIndexOrThrow(
212                         Document.COLUMN_DOCUMENT_ID)));
213         assertEquals("dir2",
214                 childCursor.getString(childCursor.getColumnIndexOrThrow(
215                         Document.COLUMN_DISPLAY_NAME)));
216         assertEquals(Document.MIME_TYPE_DIR,
217                 childCursor.getString(childCursor.getColumnIndexOrThrow(
218                         Document.COLUMN_MIME_TYPE)));
219         assertEquals(0,
220                 childCursor.getInt(childCursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
221 
222         assertTrue(childCursor.moveToNext());
223         assertEquals(
224                 createArchiveId("/dir1/dir3/").toDocumentId(),
225                 childCursor.getString(childCursor.getColumnIndexOrThrow(
226                         Document.COLUMN_DOCUMENT_ID)));
227         assertEquals("dir3",
228                 childCursor.getString(childCursor.getColumnIndexOrThrow(
229                         Document.COLUMN_DISPLAY_NAME)));
230         assertEquals(Document.MIME_TYPE_DIR,
231                 childCursor.getString(childCursor.getColumnIndexOrThrow(
232                         Document.COLUMN_MIME_TYPE)));
233         assertEquals(0,
234                 childCursor.getInt(childCursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
235         assertFalse(cursor.moveToNext());
236 
237         final Cursor childCursor2 = mArchive.queryChildDocuments(
238                 createArchiveId("/dir1/dir2/").toDocumentId(),
239                 null, null);
240         assertFalse(childCursor2.moveToFirst());
241 
242         final Cursor childCursor3 = mArchive.queryChildDocuments(
243                 createArchiveId("/dir1/dir3/").toDocumentId(),
244                 null, null);
245         assertFalse(childCursor3.moveToFirst());
246     }
247 
testGetDocumentType()248     public void testGetDocumentType() throws IOException {
249         loadArchive(mTestUtils.getNonSeekableDescriptor(R.raw.archive));
250         assertEquals(Document.MIME_TYPE_DIR, mArchive.getDocumentType(
251                 createArchiveId("/dir1/").toDocumentId()));
252         assertEquals("text/plain", mArchive.getDocumentType(
253                 createArchiveId("/file1.txt").toDocumentId()));
254     }
255 
testIsChildDocument()256     public void testIsChildDocument() throws IOException {
257         loadArchive(mTestUtils.getNonSeekableDescriptor(R.raw.archive));
258         final String documentId = createArchiveId("/").toDocumentId();
259         assertTrue(mArchive.isChildDocument(documentId,
260                 createArchiveId("/dir1/").toDocumentId()));
261         assertFalse(mArchive.isChildDocument(documentId,
262                 createArchiveId("/this-does-not-exist").toDocumentId()));
263         assertTrue(mArchive.isChildDocument(
264                 createArchiveId("/dir1/").toDocumentId(),
265                 createArchiveId("/dir1/cherries.txt").toDocumentId()));
266         assertTrue(mArchive.isChildDocument(documentId,
267                 createArchiveId("/dir1/cherries.txt").toDocumentId()));
268     }
269 
testQueryDocument()270     public void testQueryDocument() throws IOException {
271         loadArchive(mTestUtils.getNonSeekableDescriptor(R.raw.archive));
272         final Cursor cursor = mArchive.queryDocument(
273                 createArchiveId("/dir2/strawberries.txt").toDocumentId(),
274                 null);
275 
276         assertTrue(cursor.moveToFirst());
277         assertEquals(
278                 createArchiveId("/dir2/strawberries.txt").toDocumentId(),
279                 cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DOCUMENT_ID)));
280         assertEquals("strawberries.txt",
281                 cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DISPLAY_NAME)));
282         assertEquals("text/plain",
283                 cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE)));
284         assertEquals(21,
285                 cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
286     }
287 
testOpenDocument()288     public void testOpenDocument() throws IOException, ErrnoException {
289         loadArchive(mTestUtils.getSeekableDescriptor(R.raw.archive));
290         commonTestOpenDocument();
291     }
292 
testOpenDocument_NonSeekable()293     public void testOpenDocument_NonSeekable() throws IOException, ErrnoException {
294         loadArchive(mTestUtils.getNonSeekableDescriptor(R.raw.archive));
295         commonTestOpenDocument();
296     }
297 
298     // Common part of testOpenDocument and testOpenDocument_NonSeekable.
commonTestOpenDocument()299     void commonTestOpenDocument() throws IOException, ErrnoException {
300         final ParcelFileDescriptor descriptor = mArchive.openDocument(
301                 createArchiveId("/dir2/strawberries.txt").toDocumentId(),
302                 "r", null /* signal */);
303         assertTrue(Archive.canSeek(descriptor));
304         try (final ParcelFileDescriptor.AutoCloseInputStream inputStream =
305                 new ParcelFileDescriptor.AutoCloseInputStream(descriptor)) {
306             Os.lseek(descriptor.getFileDescriptor(), "I love ".length(), OsConstants.SEEK_SET);
307             assertEquals("strawberries!", new Scanner(inputStream).nextLine());
308             Os.lseek(descriptor.getFileDescriptor(), 0, OsConstants.SEEK_SET);
309             assertEquals("I love strawberries!", new Scanner(inputStream).nextLine());
310         }
311     }
312 
testCanSeek()313     public void testCanSeek() throws IOException {
314         assertTrue(Archive.canSeek(mTestUtils.getSeekableDescriptor(R.raw.archive)));
315         assertFalse(Archive.canSeek(mTestUtils.getNonSeekableDescriptor(R.raw.archive)));
316     }
317 
testBrokenArchive()318     public void testBrokenArchive() throws IOException {
319         loadArchive(mTestUtils.getNonSeekableDescriptor(R.raw.archive));
320         final Cursor cursor = mArchive.queryChildDocuments(
321                 createArchiveId("/").toDocumentId(), null, null);
322     }
323 }
324