10c3c695469715288568a514842b157c05df430a0Steve McKay/*
20c3c695469715288568a514842b157c05df430a0Steve McKay * Copyright (C) 2015 The Android Open Source Project
30c3c695469715288568a514842b157c05df430a0Steve McKay *
40c3c695469715288568a514842b157c05df430a0Steve McKay * Licensed under the Apache License, Version 2.0 (the "License");
50c3c695469715288568a514842b157c05df430a0Steve McKay * you may not use this file except in compliance with the License.
60c3c695469715288568a514842b157c05df430a0Steve McKay * You may obtain a copy of the License at
70c3c695469715288568a514842b157c05df430a0Steve McKay *
80c3c695469715288568a514842b157c05df430a0Steve McKay *      http://www.apache.org/licenses/LICENSE-2.0
90c3c695469715288568a514842b157c05df430a0Steve McKay *
100c3c695469715288568a514842b157c05df430a0Steve McKay * Unless required by applicable law or agreed to in writing, software
110c3c695469715288568a514842b157c05df430a0Steve McKay * distributed under the License is distributed on an "AS IS" BASIS,
120c3c695469715288568a514842b157c05df430a0Steve McKay * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130c3c695469715288568a514842b157c05df430a0Steve McKay * See the License for the specific language governing permissions and
140c3c695469715288568a514842b157c05df430a0Steve McKay * limitations under the License.
150c3c695469715288568a514842b157c05df430a0Steve McKay */
160c3c695469715288568a514842b157c05df430a0Steve McKay
170c3c695469715288568a514842b157c05df430a0Steve McKaypackage com.android.documentsui;
180c3c695469715288568a514842b157c05df430a0Steve McKay
19ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKayimport static android.provider.DocumentsContract.buildChildDocumentsUri;
20ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKayimport static android.provider.DocumentsContract.buildDocumentUri;
21ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKayimport static android.provider.DocumentsContract.buildRootsUri;
220c3c695469715288568a514842b157c05df430a0Steve McKayimport static com.android.documentsui.model.DocumentInfo.getCursorString;
232ed9f813b0870cfa11032aa9c9c10be0bee4b64bSteve McKayimport static com.android.internal.util.Preconditions.checkArgument;
24ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKayimport static junit.framework.Assert.assertEquals;
25ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKayimport static junit.framework.Assert.assertNotNull;
26ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKayimport static junit.framework.Assert.fail;
270c3c695469715288568a514842b157c05df430a0Steve McKay
280c3c695469715288568a514842b157c05df430a0Steve McKayimport android.content.ContentProviderClient;
290c3c695469715288568a514842b157c05df430a0Steve McKayimport android.database.Cursor;
300c3c695469715288568a514842b157c05df430a0Steve McKayimport android.net.Uri;
31ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKayimport android.os.Bundle;
32ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKayimport android.os.ParcelFileDescriptor;
33ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKayimport android.os.ParcelFileDescriptor.AutoCloseInputStream;
34ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKayimport android.os.ParcelFileDescriptor.AutoCloseOutputStream;
350c3c695469715288568a514842b157c05df430a0Steve McKayimport android.os.RemoteException;
360c3c695469715288568a514842b157c05df430a0Steve McKayimport android.provider.DocumentsContract;
370c3c695469715288568a514842b157c05df430a0Steve McKayimport android.provider.DocumentsContract.Document;
380c3c695469715288568a514842b157c05df430a0Steve McKayimport android.provider.DocumentsContract.Root;
39ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKayimport android.support.annotation.Nullable;
40ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKayimport android.test.MoreAsserts;
412ed9f813b0870cfa11032aa9c9c10be0bee4b64bSteve McKayimport android.text.TextUtils;
420c3c695469715288568a514842b157c05df430a0Steve McKay
43ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKayimport com.android.documentsui.model.DocumentInfo;
440c3c695469715288568a514842b157c05df430a0Steve McKayimport com.android.documentsui.model.RootInfo;
450c3c695469715288568a514842b157c05df430a0Steve McKay
46ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKayimport com.google.android.collect.Lists;
47ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
480c3c695469715288568a514842b157c05df430a0Steve McKayimport libcore.io.IoUtils;
49ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKayimport libcore.io.Streams;
50ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
51ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKayimport java.io.IOException;
52ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKayimport java.util.ArrayList;
53ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKayimport java.util.List;
540c3c695469715288568a514842b157c05df430a0Steve McKay
550c3c695469715288568a514842b157c05df430a0Steve McKay/**
560c3c695469715288568a514842b157c05df430a0Steve McKay * Provides support for creation of documents in a test settings.
570c3c695469715288568a514842b157c05df430a0Steve McKay */
580c3c695469715288568a514842b157c05df430a0Steve McKaypublic class DocumentsProviderHelper {
590c3c695469715288568a514842b157c05df430a0Steve McKay
600c3c695469715288568a514842b157c05df430a0Steve McKay    private final String mAuthority;
61ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    private final ContentProviderClient mClient;
620c3c695469715288568a514842b157c05df430a0Steve McKay
630c3c695469715288568a514842b157c05df430a0Steve McKay    public DocumentsProviderHelper(String authority, ContentProviderClient client) {
642ed9f813b0870cfa11032aa9c9c10be0bee4b64bSteve McKay        checkArgument(!TextUtils.isEmpty(authority));
650c3c695469715288568a514842b157c05df430a0Steve McKay        mAuthority = authority;
66ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        mClient = client;
670c3c695469715288568a514842b157c05df430a0Steve McKay    }
680c3c695469715288568a514842b157c05df430a0Steve McKay
69ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public RootInfo getRoot(String documentId) throws RemoteException {
70ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        final Uri rootsUri = buildRootsUri(mAuthority);
710c3c695469715288568a514842b157c05df430a0Steve McKay        Cursor cursor = null;
720c3c695469715288568a514842b157c05df430a0Steve McKay        try {
730c3c695469715288568a514842b157c05df430a0Steve McKay            cursor = mClient.query(rootsUri, null, null, null, null);
740c3c695469715288568a514842b157c05df430a0Steve McKay            while (cursor.moveToNext()) {
75ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay                if (documentId.equals(getCursorString(cursor, Root.COLUMN_ROOT_ID))) {
760c3c695469715288568a514842b157c05df430a0Steve McKay                    return RootInfo.fromRootsCursor(mAuthority, cursor);
770c3c695469715288568a514842b157c05df430a0Steve McKay                }
780c3c695469715288568a514842b157c05df430a0Steve McKay            }
79ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            throw new IllegalArgumentException("Can't find matching root for id=" + documentId);
800c3c695469715288568a514842b157c05df430a0Steve McKay        } catch (Exception e) {
81ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            throw new RuntimeException("Can't load root for id=" + documentId , e);
820c3c695469715288568a514842b157c05df430a0Steve McKay        } finally {
830c3c695469715288568a514842b157c05df430a0Steve McKay            IoUtils.closeQuietly(cursor);
840c3c695469715288568a514842b157c05df430a0Steve McKay        }
850c3c695469715288568a514842b157c05df430a0Steve McKay    }
860c3c695469715288568a514842b157c05df430a0Steve McKay
870c3c695469715288568a514842b157c05df430a0Steve McKay    public Uri createDocument(Uri parentUri, String mimeType, String name) {
880c3c695469715288568a514842b157c05df430a0Steve McKay        if (name.contains("/")) {
890c3c695469715288568a514842b157c05df430a0Steve McKay            throw new IllegalArgumentException("Name and mimetype probably interposed.");
900c3c695469715288568a514842b157c05df430a0Steve McKay        }
910c3c695469715288568a514842b157c05df430a0Steve McKay        try {
92ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            Uri uri = DocumentsContract.createDocument(mClient, parentUri, mimeType, name);
93ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            return uri;
940c3c695469715288568a514842b157c05df430a0Steve McKay        } catch (RemoteException e) {
95c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski            throw new RuntimeException("Couldn't create document: " + name + " with mimetype "
96c7b832202a8f1f91e378e255e61c4aa703f53394Tomasz Mikolajewski                    + mimeType, e);
970c3c695469715288568a514842b157c05df430a0Steve McKay        }
980c3c695469715288568a514842b157c05df430a0Steve McKay    }
990c3c695469715288568a514842b157c05df430a0Steve McKay
100ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public Uri createDocument(String parentId, String mimeType, String name) {
101ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        Uri parentUri = buildDocumentUri(mAuthority, parentId);
102ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        return createDocument(parentUri, mimeType, name);
103ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
104ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
105ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public Uri createDocument(RootInfo root, String mimeType, String name) {
106ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        return createDocument(root.documentId, mimeType, name);
107ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
108ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
1091008a11233c9edb6544a1e4d65e291bb16066fa3Tomasz Mikolajewski    public Uri createDocumentWithFlags(String documentId, String mimeType, String name, int flags,
1101008a11233c9edb6544a1e4d65e291bb16066fa3Tomasz Mikolajewski            String... streamTypes)
1110950df196fc5a85910e18510eb8dea2a9f233312Aga Wronska            throws RemoteException {
1120950df196fc5a85910e18510eb8dea2a9f233312Aga Wronska        Bundle in = new Bundle();
1130950df196fc5a85910e18510eb8dea2a9f233312Aga Wronska        in.putInt(StubProvider.EXTRA_FLAGS, flags);
1140950df196fc5a85910e18510eb8dea2a9f233312Aga Wronska        in.putString(StubProvider.EXTRA_PARENT_ID, documentId);
1150950df196fc5a85910e18510eb8dea2a9f233312Aga Wronska        in.putString(Document.COLUMN_MIME_TYPE, mimeType);
1160950df196fc5a85910e18510eb8dea2a9f233312Aga Wronska        in.putString(Document.COLUMN_DISPLAY_NAME, name);
1171008a11233c9edb6544a1e4d65e291bb16066fa3Tomasz Mikolajewski        in.putStringArrayList(StubProvider.EXTRA_STREAM_TYPES, Lists.newArrayList(streamTypes));
1180950df196fc5a85910e18510eb8dea2a9f233312Aga Wronska
1190950df196fc5a85910e18510eb8dea2a9f233312Aga Wronska        Bundle out = mClient.call("createDocumentWithFlags", null, in);
1200950df196fc5a85910e18510eb8dea2a9f233312Aga Wronska        Uri uri = out.getParcelable(DocumentsContract.EXTRA_URI);
1210950df196fc5a85910e18510eb8dea2a9f233312Aga Wronska        return uri;
1220950df196fc5a85910e18510eb8dea2a9f233312Aga Wronska    }
1230950df196fc5a85910e18510eb8dea2a9f233312Aga Wronska
1240c3c695469715288568a514842b157c05df430a0Steve McKay    public Uri createFolder(Uri parentUri, String name) {
1250c3c695469715288568a514842b157c05df430a0Steve McKay        return createDocument(parentUri, Document.MIME_TYPE_DIR, name);
1260c3c695469715288568a514842b157c05df430a0Steve McKay    }
1270c3c695469715288568a514842b157c05df430a0Steve McKay
128ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public Uri createFolder(String parentId, String name) {
129ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        Uri parentUri = buildDocumentUri(mAuthority, parentId);
130ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        return createDocument(parentUri, Document.MIME_TYPE_DIR, name);
1310c3c695469715288568a514842b157c05df430a0Steve McKay    }
1320c3c695469715288568a514842b157c05df430a0Steve McKay
1330c3c695469715288568a514842b157c05df430a0Steve McKay    public Uri createFolder(RootInfo root, String name) {
1340c3c695469715288568a514842b157c05df430a0Steve McKay        return createDocument(root, Document.MIME_TYPE_DIR, name);
1350c3c695469715288568a514842b157c05df430a0Steve McKay    }
136ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
137ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public void writeDocument(Uri documentUri, byte[] contents)
138ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            throws RemoteException, IOException {
139ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        ParcelFileDescriptor file = mClient.openFile(documentUri, "w", null);
140ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        try (AutoCloseOutputStream out = new AutoCloseOutputStream(file)) {
141ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            out.write(contents, 0, contents.length);
142ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        }
143ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
144ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
145ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public byte[] readDocument(Uri documentUri) throws RemoteException, IOException {
146ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        ParcelFileDescriptor file = mClient.openFile(documentUri, "r", null);
147ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        byte[] buf = null;
148ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        try (AutoCloseInputStream in = new AutoCloseInputStream(file)) {
149ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            buf = Streams.readFully(in);
150ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        }
151ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        return buf;
152ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
153ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
154ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public void assertChildCount(Uri parentUri, int expected) throws Exception {
155ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        List<DocumentInfo> children = listChildren(parentUri);
156ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        assertEquals("Incorrect file count after copy", expected, children.size());
157ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
158ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
159ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public void assertChildCount(String parentId, int expected) throws Exception {
160ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        List<DocumentInfo> children = listChildren(parentId);
161ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        assertEquals("Incorrect file count after copy", expected, children.size());
162ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
163ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
164ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public void assertChildCount(RootInfo root, int expected) throws Exception {
165ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        assertChildCount(root.documentId, expected);
166ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
167ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
168ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public void assertHasFile(Uri parentUri, String name) throws Exception {
169ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        List<DocumentInfo> children = listChildren(parentUri);
170ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        for (DocumentInfo child : children) {
171ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            if (name.equals(child.displayName) && !child.isDirectory()) {
172ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay                return;
173ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            }
174ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        }
175ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        fail("Could not find file named=" + name + " in children " + children);
176ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
177ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
178ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public void assertHasFile(String parentId, String name) throws Exception {
179ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        Uri parentUri = buildDocumentUri(mAuthority, parentId);
180ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        assertHasFile(parentUri, name);
181ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
182ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
183ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public void assertHasFile(RootInfo root, String name) throws Exception {
184ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        assertHasFile(root.documentId, name);
185ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
186ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
187ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public void assertHasDirectory(Uri parentUri, String name) throws Exception {
188ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        List<DocumentInfo> children = listChildren(parentUri);
189ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        for (DocumentInfo child : children) {
190ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            if (name.equals(child.displayName) && child.isDirectory()) {
191ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay                return;
192ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            }
193ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        }
194ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        fail("Could not find name=" + name + " in children " + children);
195ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
196ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
197ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public void assertHasDirectory(String parentId, String name) throws Exception {
198ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        Uri parentUri = buildDocumentUri(mAuthority, parentId);
199ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        assertHasDirectory(parentUri, name);
200ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
201ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
202ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public void assertHasDirectory(RootInfo root, String name) throws Exception {
203ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        assertHasDirectory(root.documentId, name);
204ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
205ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
206ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public void assertDoesNotExist(Uri parentUri, String name) throws Exception {
207ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        List<DocumentInfo> children = listChildren(parentUri);
208ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        for (DocumentInfo child : children) {
209ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            if (name.equals(child.displayName)) {
210ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay                fail("Found name=" + name + " in children " + children);
211ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            }
212ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        }
213ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
214ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
215ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public void assertDoesNotExist(String parentId, String name) throws Exception {
216ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        Uri parentUri = buildDocumentUri(mAuthority, parentId);
217ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        assertDoesNotExist(parentUri, name);
218ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
219ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
220ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public void assertDoesNotExist(RootInfo root, String name) throws Exception {
221ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        assertDoesNotExist(root.getUri(), name);
222ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
223ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
224ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public @Nullable DocumentInfo findFile(String parentId, String name)
225ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            throws Exception {
226ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        List<DocumentInfo> children = listChildren(parentId);
227ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        for (DocumentInfo child : children) {
228ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            if (name.equals(child.displayName)) {
229ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay                return child;
230ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            }
231ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        }
232ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        return null;
233ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
234ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
235ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public DocumentInfo findDocument(String parentId, String name) throws Exception {
236ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        List<DocumentInfo> children = listChildren(parentId);
237ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        for (DocumentInfo child : children) {
238ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            if (name.equals(child.displayName)) {
239ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay                return child;
240ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            }
241ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        }
242ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        return null;
243ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
244ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
245ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public DocumentInfo findDocument(Uri parentUri, String name) throws Exception {
246ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        List<DocumentInfo> children = listChildren(parentUri);
247ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        for (DocumentInfo child : children) {
248ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            if (name.equals(child.displayName)) {
249ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay                return child;
250ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            }
251ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        }
252ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        return null;
253ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
254ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
255ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public List<DocumentInfo> listChildren(Uri parentUri) throws Exception {
256ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        String id = DocumentsContract.getDocumentId(parentUri);
257ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        return listChildren(id);
258ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
259ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
260ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public List<DocumentInfo> listChildren(String documentId) throws Exception {
261ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        Uri uri = buildChildDocumentsUri(mAuthority, documentId);
262ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        List<DocumentInfo> children = new ArrayList<>();
263ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        try (Cursor cursor = mClient.query(uri, null, null, null, null, null)) {
2642ed9f813b0870cfa11032aa9c9c10be0bee4b64bSteve McKay            Cursor wrapper = new RootCursorWrapper(mAuthority, "totally-fake", cursor, 100);
2652ed9f813b0870cfa11032aa9c9c10be0bee4b64bSteve McKay            while (wrapper.moveToNext()) {
2662ed9f813b0870cfa11032aa9c9c10be0bee4b64bSteve McKay                children.add(DocumentInfo.fromDirectoryCursor(wrapper));
267ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            }
268ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        }
269ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        return children;
270ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
271ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
272ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public void assertFileContents(Uri documentUri, byte[] expected) throws Exception {
2732ed9f813b0870cfa11032aa9c9c10be0bee4b64bSteve McKay        MoreAsserts.assertEquals(
2742ed9f813b0870cfa11032aa9c9c10be0bee4b64bSteve McKay                "Copied file contents differ",
2752ed9f813b0870cfa11032aa9c9c10be0bee4b64bSteve McKay                expected, readDocument(documentUri));
276ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
277ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
278ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public void assertFileContents(String parentId, String fileName, byte[] expected)
279ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            throws Exception {
280ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        DocumentInfo file = findFile(parentId, fileName);
281ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        assertNotNull(file);
282ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        assertFileContents(file.derivedUri, expected);
283ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
284ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
285ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    /**
286ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay     * A helper method for StubProvider only. Won't work with other providers.
287ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay     * @throws RemoteException
288ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay     */
289ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    public Uri createVirtualFile(
290ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay            RootInfo root, String path, String mimeType, byte[] content, String... streamTypes)
291ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay                    throws RemoteException {
292ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
293ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        Bundle args = new Bundle();
294ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        args.putString(StubProvider.EXTRA_ROOT, root.rootId);
295ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        args.putString(StubProvider.EXTRA_PATH, path);
296ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        args.putString(Document.COLUMN_MIME_TYPE, mimeType);
297ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        args.putStringArrayList(StubProvider.EXTRA_STREAM_TYPES, Lists.newArrayList(streamTypes));
298ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        args.putByteArray(StubProvider.EXTRA_CONTENT, content);
299ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
300ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        Bundle result = mClient.call("createVirtualFile", null, args);
301ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        String documentId = result.getString(Document.COLUMN_DOCUMENT_ID);
302ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay
303ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay        return DocumentsContract.buildDocumentUri(mAuthority, documentId);
304ecbf3c504c5ec7ccb3e2be7f4dd175ebe634139dSteve McKay    }
3050950df196fc5a85910e18510eb8dea2a9f233312Aga Wronska
3060c3c695469715288568a514842b157c05df430a0Steve McKay}
307