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 android.support.provider.tests;
18
19import android.database.Cursor;
20import android.net.Uri;
21import android.os.ParcelFileDescriptor;
22import android.provider.DocumentsContract.Document;
23import android.support.provider.DocumentArchive;
24import android.test.AndroidTestCase;
25import android.util.Log;
26
27import java.io.File;
28import java.io.FileOutputStream;
29import java.io.IOException;
30import java.io.InputStream;
31import java.util.Scanner;
32
33/**
34 * Tests for DocumentArchive.
35 */
36public class DocumentArchiveTest extends AndroidTestCase {
37    private static final String DOCUMENT_ID = "document-id";
38    private static final char DELIMITER = ':';
39    private static final String NOTIFICATION_URI = "content://notification-uri";
40    private DocumentArchive mArchive = null;
41
42    public void loadArchive(int resource) {
43        // Extract the file from resources.
44        File file = null;
45        try {
46            file = File.createTempFile("android.support.provider.tests{",
47                    "}.zip", mContext.getCacheDir());
48            try (
49                final FileOutputStream outputStream =
50                        new ParcelFileDescriptor.AutoCloseOutputStream(
51                                ParcelFileDescriptor.open(
52                                        file, ParcelFileDescriptor.MODE_WRITE_ONLY));
53                final InputStream inputStream =
54                        mContext.getResources().openRawResource(resource);
55            ) {
56                final byte[] buffer = new byte[32 * 1024];
57                int bytes;
58                while ((bytes = inputStream.read(buffer)) != -1) {
59                    outputStream.write(buffer, 0, bytes);
60                }
61                outputStream.flush();
62                mArchive = DocumentArchive.createForLocalFile(
63                      mContext,
64                      file,
65                      DOCUMENT_ID,
66                      DELIMITER,
67                      Uri.parse(NOTIFICATION_URI));
68
69            }
70        } catch (IOException e) {
71            fail(String.valueOf(e));
72        } finally {
73            // On UNIX the file will be still available for processes which opened it, even
74            // after deleting it. Remove it ASAP, as it won't be used by anyone else.
75            if (file != null) {
76                file.delete();
77            }
78        }
79    }
80
81    @Override
82    public void tearDown() {
83        if (mArchive != null) {
84            mArchive.close();
85        }
86    }
87
88    public void testQueryChildDocument() throws IOException {
89        loadArchive(R.raw.archive);
90        final Cursor cursor = mArchive.queryChildDocuments(DOCUMENT_ID, null, null);
91
92        assertTrue(cursor.moveToFirst());
93        assertEquals("document-id:dir1/",
94                cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DOCUMENT_ID)));
95        assertEquals("dir1",
96                cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DISPLAY_NAME)));
97        assertEquals(Document.MIME_TYPE_DIR,
98                cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE)));
99        assertEquals(0,
100                cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
101
102        assertTrue(cursor.moveToNext());
103        assertEquals("document-id:dir2/",
104                cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DOCUMENT_ID)));
105        assertEquals("dir2",
106                cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DISPLAY_NAME)));
107        assertEquals(Document.MIME_TYPE_DIR,
108                cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE)));
109        assertEquals(0,
110                cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
111
112        assertTrue(cursor.moveToNext());
113        assertEquals("document-id:file1.txt",
114                cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DOCUMENT_ID)));
115        assertEquals("file1.txt",
116                cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DISPLAY_NAME)));
117        assertEquals("text/plain",
118                cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE)));
119        assertEquals(13,
120                cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
121
122        assertFalse(cursor.moveToNext());
123
124        // Check if querying children works too.
125        final Cursor childCursor = mArchive.queryChildDocuments("document-id:dir1/", null, null);
126
127        assertTrue(childCursor.moveToFirst());
128        assertEquals("document-id:dir1/cherries.txt",
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
141    public void testQueryChildDocument_NoDirs() throws IOException {
142        loadArchive(R.raw.no_dirs);
143        final Cursor cursor = mArchive.queryChildDocuments(DOCUMENT_ID, null, null);
144
145        assertTrue(cursor.moveToFirst());
146        assertEquals("document-id:dir1/",
147                cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DOCUMENT_ID)));
148        assertEquals("dir1",
149                cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DISPLAY_NAME)));
150        assertEquals(Document.MIME_TYPE_DIR,
151                cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE)));
152        assertEquals(0,
153                cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
154        assertFalse(cursor.moveToNext());
155
156        final Cursor childCursor = mArchive.queryChildDocuments("document-id:dir1/", null, null);
157
158        assertTrue(childCursor.moveToFirst());
159        assertEquals("document-id:dir1/dir2/",
160                childCursor.getString(childCursor.getColumnIndexOrThrow(
161                        Document.COLUMN_DOCUMENT_ID)));
162        assertEquals("dir2",
163                childCursor.getString(childCursor.getColumnIndexOrThrow(
164                        Document.COLUMN_DISPLAY_NAME)));
165        assertEquals(Document.MIME_TYPE_DIR,
166                childCursor.getString(childCursor.getColumnIndexOrThrow(
167                        Document.COLUMN_MIME_TYPE)));
168        assertEquals(0,
169                childCursor.getInt(childCursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
170        assertFalse(childCursor.moveToNext());
171
172        final Cursor childCursor2 = mArchive.queryChildDocuments(
173                "document-id:dir1/dir2/", null, null);
174
175        assertTrue(childCursor2.moveToFirst());
176        assertEquals("document-id:dir1/dir2/cherries.txt",
177                childCursor2.getString(childCursor.getColumnIndexOrThrow(
178                        Document.COLUMN_DOCUMENT_ID)));
179        assertFalse(childCursor2.moveToNext());
180    }
181
182    public void testQueryChildDocument_EmptyDirs() throws IOException {
183        loadArchive(R.raw.empty_dirs);
184        final Cursor cursor = mArchive.queryChildDocuments(DOCUMENT_ID, null, null);
185
186        assertTrue(cursor.moveToFirst());
187        assertEquals("document-id:dir1/",
188                cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DOCUMENT_ID)));
189        assertEquals("dir1",
190                cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DISPLAY_NAME)));
191        assertEquals(Document.MIME_TYPE_DIR,
192                cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE)));
193        assertEquals(0,
194                cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
195        assertFalse(cursor.moveToNext());
196
197        final Cursor childCursor = mArchive.queryChildDocuments("document-id:dir1/", null, null);
198
199        assertTrue(childCursor.moveToFirst());
200        assertEquals("document-id:dir1/dir2/",
201                childCursor.getString(childCursor.getColumnIndexOrThrow(
202                        Document.COLUMN_DOCUMENT_ID)));
203        assertEquals("dir2",
204                childCursor.getString(childCursor.getColumnIndexOrThrow(
205                        Document.COLUMN_DISPLAY_NAME)));
206        assertEquals(Document.MIME_TYPE_DIR,
207                childCursor.getString(childCursor.getColumnIndexOrThrow(
208                        Document.COLUMN_MIME_TYPE)));
209        assertEquals(0,
210                childCursor.getInt(childCursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
211
212        assertTrue(childCursor.moveToNext());
213        assertEquals("document-id:dir1/dir3/",
214                childCursor.getString(childCursor.getColumnIndexOrThrow(
215                        Document.COLUMN_DOCUMENT_ID)));
216        assertEquals("dir3",
217                childCursor.getString(childCursor.getColumnIndexOrThrow(
218                        Document.COLUMN_DISPLAY_NAME)));
219        assertEquals(Document.MIME_TYPE_DIR,
220                childCursor.getString(childCursor.getColumnIndexOrThrow(
221                        Document.COLUMN_MIME_TYPE)));
222        assertEquals(0,
223                childCursor.getInt(childCursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
224        assertFalse(cursor.moveToNext());
225
226        final Cursor childCursor2 = mArchive.queryChildDocuments(
227                "document-id:dir1/dir2/", null, null);
228        assertFalse(childCursor2.moveToFirst());
229
230        final Cursor childCursor3 = mArchive.queryChildDocuments(
231                "document-id:dir1/dir3/", null, null);
232        assertFalse(childCursor3.moveToFirst());
233    }
234
235    public void testGetDocumentType() throws IOException {
236        loadArchive(R.raw.archive);
237        assertEquals(Document.MIME_TYPE_DIR, mArchive.getDocumentType("document-id:dir1/"));
238        assertEquals("text/plain", mArchive.getDocumentType("document-id:file1.txt"));
239    }
240
241    public void testIsChildDocument() throws IOException {
242        loadArchive(R.raw.archive);
243        assertTrue(mArchive.isChildDocument(DOCUMENT_ID, "document-id:dir1/"));
244        assertFalse(mArchive.isChildDocument(DOCUMENT_ID, "document-id:this-does-not-exist"));
245        assertTrue(mArchive.isChildDocument("document-id:dir1/", "document-id:dir1/cherries.txt"));
246        assertTrue(mArchive.isChildDocument(DOCUMENT_ID, "document-id:dir1/cherries.txt"));
247    }
248
249    public void testQueryDocument() throws IOException {
250        loadArchive(R.raw.archive);
251        final Cursor cursor = mArchive.queryDocument("document-id:dir2/strawberries.txt", null);
252
253        assertTrue(cursor.moveToFirst());
254        assertEquals("document-id:dir2/strawberries.txt",
255                cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DOCUMENT_ID)));
256        assertEquals("strawberries.txt",
257                cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_DISPLAY_NAME)));
258        assertEquals("text/plain",
259                cursor.getString(cursor.getColumnIndexOrThrow(Document.COLUMN_MIME_TYPE)));
260        assertEquals(21,
261                cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_SIZE)));
262    }
263
264    public void testOpenDocument() throws IOException {
265        loadArchive(R.raw.archive);
266        final ParcelFileDescriptor descriptor = mArchive.openDocument(
267                "document-id:dir2/strawberries.txt", "r", null /* signal */);
268        try (final ParcelFileDescriptor.AutoCloseInputStream inputStream =
269                new ParcelFileDescriptor.AutoCloseInputStream(descriptor)) {
270            assertEquals("I love strawberries!", new Scanner(inputStream).nextLine());
271        }
272    }
273}
274