• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.documentsui.archives;
18 
19 import com.android.documentsui.archives.ArchivesProvider;
20 import com.android.documentsui.archives.Archive;
21 import com.android.documentsui.tests.R;
22 
23 import android.content.ContentProviderClient;
24 import android.content.ContentResolver;
25 import android.content.Context;
26 import android.database.ContentObserver;
27 import android.database.Cursor;
28 import android.net.Uri;
29 import android.os.Bundle;
30 import android.os.ParcelFileDescriptor;
31 import android.provider.DocumentsContract.Document;
32 import android.provider.DocumentsContract;
33 import android.support.test.InstrumentationRegistry;
34 import android.test.AndroidTestCase;
35 import android.test.suitebuilder.annotation.MediumTest;
36 import android.text.TextUtils;
37 
38 import java.io.File;
39 import java.io.FileOutputStream;
40 import java.io.IOException;
41 import java.io.InputStream;
42 import java.util.Scanner;
43 import java.util.concurrent.ExecutorService;
44 import java.util.concurrent.Executors;
45 import java.util.concurrent.TimeUnit;
46 import java.util.concurrent.CountDownLatch;
47 
48 @MediumTest
49 public class ArchivesProviderTest extends AndroidTestCase {
50     private static final Uri ARCHIVE_URI = Uri.parse("content://i/love/strawberries");
51     private static final String NOTIFICATION_URI =
52             "content://com.android.documentsui.archives/notification-uri";
53     private ExecutorService mExecutor = null;
54     private Archive mArchive = null;
55     private TestUtils mTestUtils = null;
56 
57     @Override
setUp()58     public void setUp() throws Exception {
59         super.setUp();
60         mExecutor = Executors.newSingleThreadExecutor();
61         mTestUtils = new TestUtils(InstrumentationRegistry.getTargetContext(),
62                 InstrumentationRegistry.getContext(), mExecutor);
63     }
64 
65     @Override
tearDown()66     public void tearDown() throws Exception {
67         mExecutor.shutdown();
68         assertTrue(mExecutor.awaitTermination(3 /* timeout */, TimeUnit.SECONDS));
69         super.tearDown();
70     }
71 
testQueryRoots()72     public void testQueryRoots() throws InterruptedException {
73         final ContentResolver resolver = getContext().getContentResolver();
74         final Uri rootsUri = DocumentsContract.buildRootsUri(ArchivesProvider.AUTHORITY);
75         try (final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
76                 rootsUri)) {
77             final Cursor cursor = resolver.query(rootsUri, null, null, null, null, null);
78             assertNotNull("Cursor must not be null.", cursor);
79             assertEquals(0, cursor.getCount());
80         }
81     }
82 
testOpen_Success()83     public void testOpen_Success() throws InterruptedException {
84         final Uri sourceUri = DocumentsContract.buildDocumentUri(
85                 ResourcesProvider.AUTHORITY, "archive.zip");
86         final Uri archiveUri = ArchivesProvider.buildUriForArchive(sourceUri,
87                 ParcelFileDescriptor.MODE_READ_ONLY);
88 
89         final Uri childrenUri = DocumentsContract.buildChildDocumentsUri(
90                 ArchivesProvider.AUTHORITY, DocumentsContract.getDocumentId(archiveUri));
91 
92         final ContentResolver resolver = getContext().getContentResolver();
93         final CountDownLatch latch = new CountDownLatch(1);
94 
95         final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
96                 archiveUri);
97         ArchivesProvider.acquireArchive(client, archiveUri);
98 
99         {
100             final Cursor cursor = resolver.query(childrenUri, null, null, null, null, null);
101             assertNotNull("Cursor must not be null. File not found?", cursor);
102 
103             assertEquals(0, cursor.getCount());
104             final Bundle extras = cursor.getExtras();
105             assertEquals(true, extras.getBoolean(DocumentsContract.EXTRA_LOADING, false));
106             assertNull(extras.getString(DocumentsContract.EXTRA_ERROR));
107 
108             final Uri notificationUri = cursor.getNotificationUri();
109             assertNotNull(notificationUri);
110 
111             resolver.registerContentObserver(notificationUri, false, new ContentObserver(null) {
112                 @Override
113                 public void onChange(boolean selfChange, Uri uri) {
114                     latch.countDown();
115                 }
116             });
117         }
118 
119         latch.await(30, TimeUnit.SECONDS);
120         {
121             final Cursor cursor = resolver.query(childrenUri, null, null, null, null, null);
122             assertNotNull("Cursor must not be null. File not found?", cursor);
123 
124             assertEquals(3, cursor.getCount());
125             final Bundle extras = cursor.getExtras();
126             assertEquals(false, extras.getBoolean(DocumentsContract.EXTRA_LOADING, false));
127             assertNull(extras.getString(DocumentsContract.EXTRA_ERROR));
128         }
129 
130         ArchivesProvider.releaseArchive(client, archiveUri);
131         client.release();
132     }
133 
testOpen_Failure()134     public void testOpen_Failure() throws InterruptedException {
135         final Uri sourceUri = DocumentsContract.buildDocumentUri(
136                 ResourcesProvider.AUTHORITY, "broken.zip");
137         final Uri archiveUri = ArchivesProvider.buildUriForArchive(sourceUri,
138                 ParcelFileDescriptor.MODE_READ_ONLY);
139 
140         final Uri childrenUri = DocumentsContract.buildChildDocumentsUri(
141                 ArchivesProvider.AUTHORITY, DocumentsContract.getDocumentId(archiveUri));
142 
143         final ContentResolver resolver = getContext().getContentResolver();
144         final CountDownLatch latch = new CountDownLatch(1);
145 
146         final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
147                 archiveUri);
148         ArchivesProvider.acquireArchive(client, archiveUri);
149 
150         {
151             // TODO: Close this and any other cursor in this file.
152             final Cursor cursor = resolver.query(childrenUri, null, null, null, null, null);
153             assertNotNull("Cursor must not be null. File not found?", cursor);
154 
155             assertEquals(0, cursor.getCount());
156             final Bundle extras = cursor.getExtras();
157             assertEquals(true, extras.getBoolean(DocumentsContract.EXTRA_LOADING, false));
158             assertNull(extras.getString(DocumentsContract.EXTRA_ERROR));
159 
160             final Uri notificationUri = cursor.getNotificationUri();
161             assertNotNull(notificationUri);
162 
163             resolver.registerContentObserver(notificationUri, false, new ContentObserver(null) {
164                 @Override
165                 public void onChange(boolean selfChange, Uri uri) {
166                     latch.countDown();
167                 }
168             });
169         }
170 
171         latch.await(30, TimeUnit.SECONDS);
172         {
173             final Cursor cursor = resolver.query(childrenUri, null, null, null, null, null);
174             assertNotNull("Cursor must not be null. File not found?", cursor);
175 
176             assertEquals(0, cursor.getCount());
177             final Bundle extras = cursor.getExtras();
178             assertEquals(false, extras.getBoolean(DocumentsContract.EXTRA_LOADING, false));
179             assertFalse(TextUtils.isEmpty(extras.getString(DocumentsContract.EXTRA_ERROR)));
180         }
181 
182         ArchivesProvider.releaseArchive(client, archiveUri);
183         client.release();
184     }
185 
testOpen_ClosesOnRelease()186     public void testOpen_ClosesOnRelease() throws InterruptedException {
187         final Uri sourceUri = DocumentsContract.buildDocumentUri(
188                 ResourcesProvider.AUTHORITY, "broken.zip");
189         final Uri archiveUri = ArchivesProvider.buildUriForArchive(sourceUri,
190                 ParcelFileDescriptor.MODE_READ_ONLY);
191 
192         final Uri childrenUri = DocumentsContract.buildChildDocumentsUri(
193                 ArchivesProvider.AUTHORITY, DocumentsContract.getDocumentId(archiveUri));
194 
195         final ContentResolver resolver = getContext().getContentResolver();
196         final CountDownLatch latch = new CountDownLatch(1);
197 
198         final ContentProviderClient client = resolver.acquireUnstableContentProviderClient(
199                 archiveUri);
200 
201         // Acquire twice to ensure that the refcount works correctly.
202         ArchivesProvider.acquireArchive(client, archiveUri);
203         ArchivesProvider.acquireArchive(client, archiveUri);
204 
205         {
206             final Cursor cursor = resolver.query(childrenUri, null, null, null, null, null);
207             assertNotNull("Cursor must not be null. File not found?", cursor);
208         }
209 
210         ArchivesProvider.releaseArchive(client, archiveUri);
211 
212         {
213             final Cursor cursor = resolver.query(childrenUri, null, null, null, null, null);
214             assertNotNull("Cursor must not be null. File not found?", cursor);
215         }
216 
217         ArchivesProvider.releaseArchive(client, archiveUri);
218 
219         try {
220             resolver.query(childrenUri, null, null, null, null, null);
221             fail("The archive was expected to be invalited on the last release call.");
222         } catch (IllegalStateException e) {
223             // Expected.
224         }
225 
226         client.release();
227     }
228 }
229