15fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey/*
25fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * Copyright (C) 2014 The Android Open Source Project
35fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey *
45fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
55fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * you may not use this file except in compliance with the License.
65fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * You may obtain a copy of the License at
75fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey *
85fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
95fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey *
105fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
115fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
125fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * See the License for the specific language governing permissions and
145fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * limitations under the License.
155fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey */
165fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
175fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeypackage android.support.v4.provider;
185fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
195fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport android.content.ContentResolver;
205fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport android.content.UriPermission;
215fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport android.net.Uri;
225fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport android.os.Environment;
235fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport android.os.FileUtils;
245fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport android.os.SystemClock;
255fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport android.support.v4.provider.DocumentFile;
265fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport android.test.AndroidTestCase;
275fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
285fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport java.io.DataInputStream;
295fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport java.io.DataOutputStream;
305fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport java.io.File;
315fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport java.io.FileInputStream;
325fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport java.io.FileOutputStream;
335fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport java.io.IOException;
345fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport java.util.List;
355fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
365fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey/**
375fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * Tests for {@link DocumentFile}
385fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey */
395fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeypublic class DocumentFileTest extends AndroidTestCase {
405fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
415fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private Uri treeUri;
425fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
435fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private File root;
445fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private File rootFoo;
455fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private File rootMeow;
465fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private File rootMeowCat;
475fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private File rootMeowDog;
485fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private File rootMeowBar;
495fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
505fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private static final String FOO = "foo.randomext";
515fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private static final String MEOW = "meow";
525fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private static final String CAT = "cat.jpg";
535fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private static final String DOG = "DOG.PDF";
545fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private static final String BAR = "bar.png";
555fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
565fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    @Override
575fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    protected void setUp() throws Exception {
585fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        super.setUp();
595fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
605fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        final ContentResolver resolver = getContext().getContentResolver();
615fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        final List<UriPermission> perms = resolver.getPersistedUriPermissions();
625fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
635fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        if (perms.isEmpty()) {
645fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            throw new RuntimeException(
655fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                    "Failed to find outstanding grant; did you run the activity first?");
665fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        } else {
675fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            treeUri = perms.get(0).getUri();
685fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        }
695fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
705fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        root = Environment.getExternalStorageDirectory();
715fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        rootFoo = new File(root, FOO);
725fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        rootMeow = new File(root, MEOW);
735fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        rootMeowCat = new File(rootMeow, CAT);
745fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        rootMeowDog = new File(rootMeow, DOG);
755fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        rootMeowBar = new File(rootMeow, BAR);
765fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
775fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        resetRoot();
785fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
795fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
805fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private void resetRoot() throws Exception {
815fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        final File tmp = new File(root, "bark.pdf");
825fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        FileUtils.deleteContents(tmp);
835fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        tmp.delete();
845fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
855fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        FileUtils.deleteContents(rootMeow);
865fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        rootMeow.mkdir();
875fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        rootMeowBar.mkdir();
885fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
895fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        writeInt(rootFoo, 12);
905fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        writeInt(rootMeowCat, 24);
915fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        writeInt(rootMeowDog, 48);
925fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
935fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
945fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private interface DocumentTest {
955fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        public void exec(DocumentFile doc) throws Exception;
965fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
975fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
985fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public void testSimple() throws Exception {
995fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        final DocumentTest test = new DocumentTest() {
1005fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            @Override
1015fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            public void exec(DocumentFile doc) throws Exception {
1025fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                resetRoot();
1035fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue("isDirectory", doc.isDirectory());
1045fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertFalse("isFile", doc.isFile());
1055fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue("canRead", doc.canRead());
1065fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue("canWrite", doc.canWrite());
1075fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue("exists", doc.exists());
1085fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            }
1095fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        };
1105fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1115fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        test.exec(DocumentFile.fromFile(root));
1125fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        test.exec(DocumentFile.fromTreeUri(getContext(), treeUri));
1135fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
1145fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1155fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public void testTraverse() throws Exception {
1165fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        final DocumentTest test = new DocumentTest() {
1175fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            @Override
1185fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            public void exec(DocumentFile doc) throws Exception {
1195fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                resetRoot();
1205fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1215fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // Root needs to at least contain our test file and dir
1225fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final DocumentFile foo = doc.findFile(FOO);
1235fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final DocumentFile meow = doc.findFile(MEOW);
1245fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue("isFile", foo.isFile());
1255fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue("isDirectory", meow.isDirectory());
1265fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1275fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // Traverse inside, and expect to find exact number of items
1285fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                DocumentFile[] docs = meow.listFiles();
1295fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("length", 3, docs.length);
1305fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1315fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final DocumentFile cat = meow.findFile(CAT);
1325fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final DocumentFile dog = meow.findFile(DOG);
1335fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final DocumentFile bar = meow.findFile(BAR);
1345fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue("isFile", cat.isFile());
1355fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue("isFile", dog.isFile());
1365fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue("isDirectory", bar.isDirectory());
1375fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1385fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // Empty directory is empty
1395fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("length", 0, bar.listFiles().length);
1405fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            }
1415fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        };
1425fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1435fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        test.exec(DocumentFile.fromFile(root));
1445fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        test.exec(DocumentFile.fromTreeUri(getContext(), treeUri));
1455fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
1465fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1475fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public void testReadAndWrite() throws Exception {
1485fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        final DocumentTest test = new DocumentTest() {
1495fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            @Override
1505fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            public void exec(DocumentFile doc) throws Exception {
1515fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                resetRoot();
1525fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1535fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final DocumentFile foo = doc.findFile(FOO);
1545fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("file", 12, readInt(rootFoo));
1555fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("uri", 12, readInt(foo.getUri()));
1565fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1575fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // Underlying storage may not have sub-second resolution, so
1585fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // wait a few seconds.
1595fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                SystemClock.sleep(2000);
1605fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1615fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // Ensure provider write makes its way to disk
1625fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final long beforeTime = foo.lastModified();
1635fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                writeInt(foo.getUri(), 13);
1645fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final long afterTime = foo.lastModified();
1655fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1665fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("file", 13, readInt(rootFoo));
1675fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("uri", 13, readInt(foo.getUri()));
1685fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1695fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // Make sure we kicked time forward
1705fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue("lastModified", afterTime > beforeTime);
1715fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            }
1725fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        };
1735fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1745fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        test.exec(DocumentFile.fromFile(root));
1755fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        test.exec(DocumentFile.fromTreeUri(getContext(), treeUri));
1765fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
1775fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1785fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public void testMimes() throws Exception {
1795fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        final DocumentTest test = new DocumentTest() {
1805fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            @Override
1815fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            public void exec(DocumentFile doc) throws Exception {
1825fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                resetRoot();
1835fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1845fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final DocumentFile foo = doc.findFile(FOO);
1855fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final DocumentFile meow = doc.findFile(MEOW);
1865fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final DocumentFile cat = meow.findFile(CAT);
1875fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final DocumentFile dog = meow.findFile(DOG);
1885fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final DocumentFile bar = meow.findFile(BAR);
1895fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1905fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals(null, doc.getType());
1915fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("application/octet-stream", foo.getType());
1925fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals(null, meow.getType());
1935fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("image/jpeg", cat.getType());
1945fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("application/pdf", dog.getType());
1955fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals(null, bar.getType());
1965fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            }
1975fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        };
1985fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
1995fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        test.exec(DocumentFile.fromFile(root));
2005fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        test.exec(DocumentFile.fromTreeUri(getContext(), treeUri));
2015fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
2025fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2035fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public void testCreate() throws Exception {
2045fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        final DocumentTest test = new DocumentTest() {
2055fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            @Override
2065fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            public void exec(DocumentFile doc) throws Exception {
2075fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                resetRoot();
2085fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2095fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final DocumentFile meow = doc.findFile(MEOW);
2105fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("length", 3, meow.listFiles().length);
2115fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2125fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // Create file with MIME
2135fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final DocumentFile newFile = meow.createFile("text/plain", "My New File");
2145fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("My New File.txt", newFile.getName());
2155fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("text/plain", newFile.getType());
2165fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue("isFile", newFile.isFile());
2175fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertFalse("isDirectory", newFile.isDirectory());
2185fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2195fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("length", 0, newFile.length());
2205fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                writeInt(newFile.getUri(), 0);
2215fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("length", 4, newFile.length());
2225fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2235fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // Create raw file
2245fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final DocumentFile newRaw = meow.createFile("application/octet-stream",
2255fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                        "myrawfile");
2265fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("myrawfile", newRaw.getName());
2275fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("application/octet-stream", newRaw.getType());
2285fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue("isFile", newRaw.isFile());
2295fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertFalse("isDirectory", newRaw.isDirectory());
2305fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2315fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // Create directory
2325fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final DocumentFile newDir = meow.createDirectory("My New Directory.png");
2335fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("My New Directory.png", newDir.getName());
2345fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertFalse("isFile", newDir.isFile());
2355fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue("isDirectory", newDir.isDirectory());
2365fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("length", 0, newDir.listFiles().length);
2375fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2385fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // And overall dir grew
2395fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("length", 6, meow.listFiles().length);
2405fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            }
2415fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        };
2425fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2435fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        test.exec(DocumentFile.fromFile(root));
2445fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        test.exec(DocumentFile.fromTreeUri(getContext(), treeUri));
2455fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
2465fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2475fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public void testDelete() throws Exception {
2485fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        final DocumentTest test = new DocumentTest() {
2495fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            @Override
2505fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            public void exec(DocumentFile doc) throws Exception {
2515fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                resetRoot();
2525fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2535fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final DocumentFile meow = doc.findFile(MEOW);
2545fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final DocumentFile cat = meow.findFile(CAT);
2555fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                final DocumentFile dog = meow.findFile(DOG);
2565fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2575fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // Delete single file
2585fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue(cat.delete());
2595fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertNull("cat", meow.findFile(CAT));
2605fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2615fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // Other file still exists
2625fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue("exists", dog.exists());
2635fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2645fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // Delete entire tree
2655fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue(meow.delete());
2665fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertNull("meow", doc.findFile(MEOW));
2675fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2685fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // Nuking tree deleted other file
2695fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertFalse("exists", dog.exists());
2705fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            }
2715fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        };
2725fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2735fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        test.exec(DocumentFile.fromFile(root));
2745fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        test.exec(DocumentFile.fromTreeUri(getContext(), treeUri));
2755fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
2765fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2775fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    public void testRename() throws Exception {
2785fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        final DocumentTest test = new DocumentTest() {
2795fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            @Override
2805fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            public void exec(DocumentFile doc) throws Exception {
2815fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                resetRoot();
2825fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2835fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                DocumentFile meow = doc.findFile(MEOW);
2845fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                DocumentFile cat = meow.findFile(CAT);
2855fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                DocumentFile dog = meow.findFile(DOG);
2865fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue(dog.exists());
2875fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2885fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // Rename a file
2895fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("cat.jpg", cat.getName());
2905fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("image/jpeg", cat.getType());
2915fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2925fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue(cat.renameTo("music.aAc"));
2935fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("music.aAc", cat.getName());
2945fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("audio/aac", cat.getType());
2955fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
2965fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // Rename a directory
2975fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("meow", meow.getName());
2985fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals(null, meow.getType());
2995fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue(meow.isDirectory());
3005fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals(3, meow.listFiles().length);
3015fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
3025fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue(meow.renameTo("bark.pdf"));
3035fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals("bark.pdf", meow.getName());
3045fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals(null, meow.getType());
3055fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue(meow.isDirectory());
3065fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertEquals(3, meow.listFiles().length);
3075fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
3085fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // Current implementation of ExternalStorageProvider invalidates
3095fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // all children documents when directory is renamed.
3105fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertFalse(dog.exists());
3115fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
3125fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                // But we can find it again
3135fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                dog = meow.findFile(DOG);
3145fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                assertTrue(dog.exists());
3155fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            }
3165fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        };
3175fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
3185fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        test.exec(DocumentFile.fromFile(root));
3195fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        test.exec(DocumentFile.fromTreeUri(getContext(), treeUri));
3205fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
3215fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
3225fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private void writeInt(Uri uri, int value) throws IOException {
3235fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        final DataOutputStream os = new DataOutputStream(
3245fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                getContext().getContentResolver().openOutputStream(uri));
3255fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        try {
3265fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            os.writeInt(value);
3275fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        } finally {
3285fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            os.close();
3295fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        }
3305fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
3315fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
3325fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private static void writeInt(File file, int value) throws IOException {
3335fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        final DataOutputStream os = new DataOutputStream(new FileOutputStream(file));
3345fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        try {
3355fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            os.writeInt(value);
3365fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        } finally {
3375fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            os.close();
3385fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        }
3395fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
3405fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
3415fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private int readInt(Uri uri) throws IOException {
3425fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        final DataInputStream is = new DataInputStream(
3435fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey                getContext().getContentResolver().openInputStream(uri));
3445fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        try {
3455fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            return is.readInt();
3465fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        } finally {
3475fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            is.close();
3485fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        }
3495fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
3505fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey
3515fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    private static int readInt(File file) throws IOException {
3525fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        final DataInputStream is = new DataInputStream(new FileInputStream(file));
3535fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        try {
3545fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            return is.readInt();
3555fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        } finally {
3565fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey            is.close();
3575fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey        }
3585fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey    }
3595fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey}
360