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.SystemClock; 245fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport android.test.AndroidTestCase; 25120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viveretteimport android.util.Log; 265fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 275fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport java.io.DataInputStream; 285fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport java.io.DataOutputStream; 295fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport java.io.File; 305fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport java.io.FileInputStream; 315fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport java.io.FileOutputStream; 325fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport java.io.IOException; 335fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeyimport java.util.List; 345fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 355fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey/** 365fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey * Tests for {@link DocumentFile} 375fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey */ 385fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkeypublic class DocumentFileTest extends AndroidTestCase { 395fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 405fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey private Uri treeUri; 415fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 425fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey private File root; 435fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey private File rootFoo; 445fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey private File rootMeow; 455fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey private File rootMeowCat; 465fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey private File rootMeowDog; 475fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey private File rootMeowBar; 485fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 495fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey private static final String FOO = "foo.randomext"; 505fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey private static final String MEOW = "meow"; 515fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey private static final String CAT = "cat.jpg"; 525fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey private static final String DOG = "DOG.PDF"; 535fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey private static final String BAR = "bar.png"; 545fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 555fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey @Override 565fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey protected void setUp() throws Exception { 575fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey super.setUp(); 585fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 595fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final ContentResolver resolver = getContext().getContentResolver(); 605fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final List<UriPermission> perms = resolver.getPersistedUriPermissions(); 615fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 625fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey if (perms.isEmpty()) { 635fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey throw new RuntimeException( 645fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey "Failed to find outstanding grant; did you run the activity first?"); 655fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } else { 665fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey treeUri = perms.get(0).getUri(); 675fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 685fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 695fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey root = Environment.getExternalStorageDirectory(); 705fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey rootFoo = new File(root, FOO); 715fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey rootMeow = new File(root, MEOW); 725fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey rootMeowCat = new File(rootMeow, CAT); 735fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey rootMeowDog = new File(rootMeow, DOG); 745fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey rootMeowBar = new File(rootMeow, BAR); 755fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 765fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey resetRoot(); 775fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 785fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 795fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey private void resetRoot() throws Exception { 805fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final File tmp = new File(root, "bark.pdf"); 81120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette deleteContents(tmp); 825fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey tmp.delete(); 835fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 84120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette deleteContents(rootMeow); 855fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey rootMeow.mkdir(); 865fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey rootMeowBar.mkdir(); 875fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 885fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey writeInt(rootFoo, 12); 895fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey writeInt(rootMeowCat, 24); 905fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey writeInt(rootMeowDog, 48); 915fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 925fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 93120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette public static boolean deleteContents(File dir) { 94120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette File[] files = dir.listFiles(); 95120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette boolean success = true; 96120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette if (files != null) { 97120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette for (File file : files) { 98120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette if (file.isDirectory()) { 99120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette success &= deleteContents(file); 100120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette } 101120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette if (!file.delete()) { 102120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette success = false; 103120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette } 104120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette } 105120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette } 106120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette return success; 107120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette } 108120325c4bd854c49fa50b872bdd84a7fac58210cAlan Viverette 1095fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey private interface DocumentTest { 1105fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey public void exec(DocumentFile doc) throws Exception; 1115fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 1125fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 1135fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey public void testSimple() throws Exception { 1145fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentTest test = new DocumentTest() { 1155fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey @Override 1165fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey public void exec(DocumentFile doc) throws Exception { 1175fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey resetRoot(); 1185fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue("isDirectory", doc.isDirectory()); 1195fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertFalse("isFile", doc.isFile()); 1205fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue("canRead", doc.canRead()); 1215fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue("canWrite", doc.canWrite()); 1225fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue("exists", doc.exists()); 1235fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 1245fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey }; 1255fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 1265fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey test.exec(DocumentFile.fromFile(root)); 1275fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey test.exec(DocumentFile.fromTreeUri(getContext(), treeUri)); 1285fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 1295fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 1305fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey public void testTraverse() throws Exception { 1315fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentTest test = new DocumentTest() { 1325fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey @Override 1335fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey public void exec(DocumentFile doc) throws Exception { 1345fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey resetRoot(); 1355fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 1365fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // Root needs to at least contain our test file and dir 1375fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentFile foo = doc.findFile(FOO); 1385fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentFile meow = doc.findFile(MEOW); 1395fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue("isFile", foo.isFile()); 1405fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue("isDirectory", meow.isDirectory()); 1415fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 1425fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // Traverse inside, and expect to find exact number of items 1435fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey DocumentFile[] docs = meow.listFiles(); 1445fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("length", 3, docs.length); 1455fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 1465fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentFile cat = meow.findFile(CAT); 1475fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentFile dog = meow.findFile(DOG); 1485fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentFile bar = meow.findFile(BAR); 1495fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue("isFile", cat.isFile()); 1505fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue("isFile", dog.isFile()); 1515fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue("isDirectory", bar.isDirectory()); 1525fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 1535fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // Empty directory is empty 1545fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("length", 0, bar.listFiles().length); 1555fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 1565fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey }; 1575fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 1585fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey test.exec(DocumentFile.fromFile(root)); 1595fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey test.exec(DocumentFile.fromTreeUri(getContext(), treeUri)); 1605fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 1615fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 1625fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey public void testReadAndWrite() throws Exception { 1635fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentTest test = new DocumentTest() { 1645fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey @Override 1655fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey public void exec(DocumentFile doc) throws Exception { 1665fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey resetRoot(); 1675fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 1685fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentFile foo = doc.findFile(FOO); 1695fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("file", 12, readInt(rootFoo)); 1705fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("uri", 12, readInt(foo.getUri())); 1715fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 1725fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // Underlying storage may not have sub-second resolution, so 1735fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // wait a few seconds. 1745fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey SystemClock.sleep(2000); 1755fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 1765fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // Ensure provider write makes its way to disk 1775fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final long beforeTime = foo.lastModified(); 1785fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey writeInt(foo.getUri(), 13); 1795fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final long afterTime = foo.lastModified(); 1805fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 1815fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("file", 13, readInt(rootFoo)); 1825fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("uri", 13, readInt(foo.getUri())); 1835fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 1845fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // Make sure we kicked time forward 1855fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue("lastModified", afterTime > beforeTime); 1865fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 1875fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey }; 1885fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 1895fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey test.exec(DocumentFile.fromFile(root)); 1905fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey test.exec(DocumentFile.fromTreeUri(getContext(), treeUri)); 1915fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 1925fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 1935fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey public void testMimes() throws Exception { 1945fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentTest test = new DocumentTest() { 1955fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey @Override 1965fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey public void exec(DocumentFile doc) throws Exception { 1975fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey resetRoot(); 1985fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 1995fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentFile foo = doc.findFile(FOO); 2005fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentFile meow = doc.findFile(MEOW); 2015fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentFile cat = meow.findFile(CAT); 2025fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentFile dog = meow.findFile(DOG); 2035fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentFile bar = meow.findFile(BAR); 2045fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2055fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals(null, doc.getType()); 2065fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("application/octet-stream", foo.getType()); 2075fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals(null, meow.getType()); 2085fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("image/jpeg", cat.getType()); 2095fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("application/pdf", dog.getType()); 2105fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals(null, bar.getType()); 2115fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 2125fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey }; 2135fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2145fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey test.exec(DocumentFile.fromFile(root)); 2155fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey test.exec(DocumentFile.fromTreeUri(getContext(), treeUri)); 2165fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 2175fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2185fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey public void testCreate() throws Exception { 2195fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentTest test = new DocumentTest() { 2205fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey @Override 2215fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey public void exec(DocumentFile doc) throws Exception { 2225fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey resetRoot(); 2235fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2245fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentFile meow = doc.findFile(MEOW); 2255fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("length", 3, meow.listFiles().length); 2265fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2275fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // Create file with MIME 2285fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentFile newFile = meow.createFile("text/plain", "My New File"); 2295fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("My New File.txt", newFile.getName()); 2305fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("text/plain", newFile.getType()); 2315fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue("isFile", newFile.isFile()); 2325fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertFalse("isDirectory", newFile.isDirectory()); 2335fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2345fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("length", 0, newFile.length()); 2355fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey writeInt(newFile.getUri(), 0); 2365fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("length", 4, newFile.length()); 2375fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2385fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // Create raw file 2395fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentFile newRaw = meow.createFile("application/octet-stream", 2405fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey "myrawfile"); 2415fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("myrawfile", newRaw.getName()); 2425fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("application/octet-stream", newRaw.getType()); 2435fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue("isFile", newRaw.isFile()); 2445fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertFalse("isDirectory", newRaw.isDirectory()); 2455fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2465fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // Create directory 2475fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentFile newDir = meow.createDirectory("My New Directory.png"); 2485fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("My New Directory.png", newDir.getName()); 2495fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertFalse("isFile", newDir.isFile()); 2505fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue("isDirectory", newDir.isDirectory()); 2515fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("length", 0, newDir.listFiles().length); 2525fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2535fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // And overall dir grew 2545fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("length", 6, meow.listFiles().length); 2555fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 2565fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey }; 2575fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2585fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey test.exec(DocumentFile.fromFile(root)); 2595fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey test.exec(DocumentFile.fromTreeUri(getContext(), treeUri)); 2605fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 2615fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2625fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey public void testDelete() throws Exception { 2635fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentTest test = new DocumentTest() { 2645fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey @Override 2655fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey public void exec(DocumentFile doc) throws Exception { 2665fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey resetRoot(); 2675fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2685fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentFile meow = doc.findFile(MEOW); 2695fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentFile cat = meow.findFile(CAT); 2705fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentFile dog = meow.findFile(DOG); 2715fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2725fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // Delete single file 2735fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue(cat.delete()); 2745fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertNull("cat", meow.findFile(CAT)); 2755fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2765fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // Other file still exists 2775fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue("exists", dog.exists()); 2785fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2795fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // Delete entire tree 2805fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue(meow.delete()); 2815fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertNull("meow", doc.findFile(MEOW)); 2825fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2835fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // Nuking tree deleted other file 2845fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertFalse("exists", dog.exists()); 2855fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 2865fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey }; 2875fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2885fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey test.exec(DocumentFile.fromFile(root)); 2895fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey test.exec(DocumentFile.fromTreeUri(getContext(), treeUri)); 2905fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 2915fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2925fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey public void testRename() throws Exception { 2935fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DocumentTest test = new DocumentTest() { 2945fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey @Override 2955fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey public void exec(DocumentFile doc) throws Exception { 2965fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey resetRoot(); 2975fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 2985fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey DocumentFile meow = doc.findFile(MEOW); 2995fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey DocumentFile cat = meow.findFile(CAT); 3005fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey DocumentFile dog = meow.findFile(DOG); 3015fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue(dog.exists()); 3025fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 3035fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // Rename a file 3045fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("cat.jpg", cat.getName()); 3055fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("image/jpeg", cat.getType()); 3065fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 3075fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue(cat.renameTo("music.aAc")); 3085fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("music.aAc", cat.getName()); 3095fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("audio/aac", cat.getType()); 3105fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 3115fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // Rename a directory 3125fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("meow", meow.getName()); 3135fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals(null, meow.getType()); 3145fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue(meow.isDirectory()); 3155fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals(3, meow.listFiles().length); 3165fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 3175fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue(meow.renameTo("bark.pdf")); 3185fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals("bark.pdf", meow.getName()); 3195fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals(null, meow.getType()); 3205fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue(meow.isDirectory()); 3215fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertEquals(3, meow.listFiles().length); 3225fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 3235fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // Current implementation of ExternalStorageProvider invalidates 3245fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // all children documents when directory is renamed. 3255fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertFalse(dog.exists()); 3265fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 3275fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey // But we can find it again 3285fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey dog = meow.findFile(DOG); 3295fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey assertTrue(dog.exists()); 3305fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 3315fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey }; 3325fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 3335fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey test.exec(DocumentFile.fromFile(root)); 3345fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey test.exec(DocumentFile.fromTreeUri(getContext(), treeUri)); 3355fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 3365fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 3375fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey private void writeInt(Uri uri, int value) throws IOException { 3385fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DataOutputStream os = new DataOutputStream( 3395fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey getContext().getContentResolver().openOutputStream(uri)); 3405fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey try { 3415fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey os.writeInt(value); 3425fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } finally { 3435fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey os.close(); 3445fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 3455fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 3465fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 3475fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey private static void writeInt(File file, int value) throws IOException { 3485fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DataOutputStream os = new DataOutputStream(new FileOutputStream(file)); 3495fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey try { 3505fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey os.writeInt(value); 3515fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } finally { 3525fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey os.close(); 3535fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 3545fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 3555fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 3565fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey private int readInt(Uri uri) throws IOException { 3575fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DataInputStream is = new DataInputStream( 3585fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey getContext().getContentResolver().openInputStream(uri)); 3595fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey try { 3605fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey return is.readInt(); 3615fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } finally { 3625fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey is.close(); 3635fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 3645fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 3655fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey 3665fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey private static int readInt(File file) throws IOException { 3675fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey final DataInputStream is = new DataInputStream(new FileInputStream(file)); 3685fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey try { 3695fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey return is.readInt(); 3705fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } finally { 3715fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey is.close(); 3725fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 3735fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey } 3745fdfbc2e02f46509474057e4366585f6a6062cb9Jeff Sharkey} 375