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.content.ContentProviderClient;
20import android.database.ContentObserver;
21import android.database.Cursor;
22import android.net.Uri;
23import android.os.ParcelFileDescriptor;
24import android.os.RemoteException;
25import android.provider.DocumentsContract.Document;
26import android.provider.DocumentsContract;
27import android.test.AndroidTestCase;
28import android.util.Log;
29
30import java.io.File;
31import java.io.FileNotFoundException;
32import java.io.FileOutputStream;
33import java.io.IOException;
34import java.io.InputStream;
35import java.lang.IllegalArgumentException;
36import java.util.Scanner;
37import java.util.concurrent.CountDownLatch;
38
39/**
40 * Integration tests for DocumentsProvider and DocumentArchiveHelper.
41 *
42 * <p>Only checks if the provider, then helper are forwarding the calls to the
43 * underlying {@code ArchiveDocument} correctly. More detailed output testing is
44 * done in {@code DocumentArchiveTest}.
45 */
46public class IntegrationTest extends AndroidTestCase {
47    private ContentProviderClient mClient;
48
49    @Override
50    public void setUp() throws RemoteException {
51        mClient = getContext().getContentResolver().acquireContentProviderClient(
52                StubProvider.AUTHORITY);
53        assertNotNull(mClient);
54        mClient.call("reset", null, null);
55    }
56
57    @Override
58    public void tearDown() {
59        if (mClient != null) {
60            mClient.release();
61            mClient = null;
62        }
63    }
64
65    public void testQueryForChildren() throws IOException {
66        final Cursor cursor = mContext.getContentResolver().query(
67                DocumentsContract.buildChildDocumentsUri(
68                        StubProvider.AUTHORITY, StubProvider.DOCUMENT_ID),
69                        null, null, null, null);
70        assertEquals(3, cursor.getCount());
71    }
72
73    public void testQueryForDocument_Archive()
74            throws IOException, RemoteException, InterruptedException {
75        final Cursor cursor = mContext.getContentResolver().query(
76                DocumentsContract.buildDocumentUri(
77                        StubProvider.AUTHORITY, StubProvider.DOCUMENT_ID),
78                        null, null, null, null);
79        assertEquals(1, cursor.getCount());
80        assertTrue(cursor.moveToFirst());
81        assertEquals(Document.FLAG_ARCHIVE,
82                cursor.getInt(cursor.getColumnIndexOrThrow(Document.COLUMN_FLAGS)));
83    }
84
85    public void testQueryForDocument_ArchiveDescendant()
86            throws IOException, RemoteException, InterruptedException {
87        final Cursor cursor = mContext.getContentResolver().query(
88                DocumentsContract.buildDocumentUri(
89                        StubProvider.AUTHORITY, StubProvider.FILE_DOCUMENT_ID),
90                        null, null, null, null);
91        assertEquals(1, cursor.getCount());
92        assertEquals(StubProvider.NOTIFY_URI, cursor.getNotificationUri());
93
94        final CountDownLatch changeSignal = new CountDownLatch(1);
95        final ContentObserver observer = new ContentObserver(null) {
96            @Override
97            public void onChange(boolean selfChange) {
98                changeSignal.countDown();
99            }
100        };
101
102        try {
103            getContext().getContentResolver().registerContentObserver(
104                    cursor.getNotificationUri(), false /* notifyForDescendants */, observer);
105
106            // Simulate deleting the archive file, then confirm that the notification is
107            // propagated and the archive closed.
108            mClient.call("delete", null, null);
109            changeSignal.await();
110
111            mContext.getContentResolver().query(
112                    DocumentsContract.buildChildDocumentsUri(
113                            StubProvider.AUTHORITY, StubProvider.FILE_DOCUMENT_ID),
114                            null, null, null, null);
115            fail("Expected IllegalStateException, but succeeded.");
116        } catch (IllegalStateException e) {
117            // Expected, as the file is gone.
118        } finally {
119            getContext().getContentResolver().unregisterContentObserver(observer);
120        }
121    }
122
123    public void testGetType() throws IOException {
124        assertEquals("text/plain", mContext.getContentResolver().getType(
125                DocumentsContract.buildDocumentUri(
126                        StubProvider.AUTHORITY, StubProvider.FILE_DOCUMENT_ID)));
127    }
128
129    public void testOpenFileDescriptor() throws IOException {
130        final ParcelFileDescriptor descriptor = mContext.getContentResolver().openFileDescriptor(
131                DocumentsContract.buildDocumentUri(
132                        StubProvider.AUTHORITY, StubProvider.FILE_DOCUMENT_ID),
133                        "r", null);
134        assertNotNull(descriptor);
135    }
136}
137