Home | History | Annotate | Download | only in io
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package libcore.java.io;
     18 
     19 import java.io.BufferedReader;
     20 import java.io.File;
     21 import java.io.FileFilter;
     22 import java.io.FilenameFilter;
     23 import java.io.InputStreamReader;
     24 import java.io.IOException;
     25 import java.util.UUID;
     26 import libcore.io.Libcore;
     27 
     28 public class FileTest extends junit.framework.TestCase {
     29     private static File createTemporaryDirectory() throws Exception {
     30         String base = System.getProperty("java.io.tmpdir");
     31         File directory = new File(base, UUID.randomUUID().toString());
     32         assertTrue(directory.mkdirs());
     33         return directory;
     34     }
     35 
     36     private static String longString(int n) {
     37         StringBuilder result = new StringBuilder();
     38         for (int i = 0; i < n; ++i) {
     39             result.append('x');
     40         }
     41         return result.toString();
     42     }
     43 
     44     private static File createDeepStructure(File base) throws Exception {
     45         // ext has a limit of around 256 characters for each path entry.
     46         // 128 characters should be safe for everything but FAT.
     47         String longString = longString(128);
     48         // Keep creating subdirectories until the path length is greater than 1KiB.
     49         // Ubuntu 8.04's kernel is happy up to about 4KiB.
     50         File f = base;
     51         for (int i = 0; f.toString().length() <= 1024; ++i) {
     52             f = new File(f, longString);
     53             assertTrue(f.mkdir());
     54         }
     55         return f;
     56     }
     57 
     58     // Rather than test all methods, assume that if createTempFile creates a long path and
     59     // exists can see it, the code for coping with long paths (shared by all methods) works.
     60     public void test_longPath() throws Exception {
     61         File base = createTemporaryDirectory();
     62         assertTrue(createDeepStructure(base).exists());
     63     }
     64 
     65     // readlink(2) is a special case,.
     66     public void test_longReadlink() throws Exception {
     67         File base = createTemporaryDirectory();
     68         File target = createDeepStructure(base);
     69         File source = new File(base, "source");
     70         assertFalse(source.exists());
     71         assertTrue(target.exists());
     72         assertTrue(target.getCanonicalPath().length() > 1024);
     73         ln_s(target, source);
     74         assertTrue(source.exists());
     75         assertEquals(target.getCanonicalPath(), source.getCanonicalPath());
     76     }
     77 
     78     // TODO: File.list is a special case too, but I haven't fixed it yet, and the new code,
     79     // like the old code, will die of a native buffer overrun if we exercise it.
     80 
     81     public void test_emptyFilename() throws Exception {
     82         // The behavior of the empty filename is an odd mixture.
     83         File f = new File("");
     84         // Mostly it behaves like an invalid path...
     85         assertFalse(f.canExecute());
     86         assertFalse(f.canRead());
     87         assertFalse(f.canWrite());
     88         try {
     89             f.createNewFile();
     90             fail("expected IOException");
     91         } catch (IOException expected) {
     92         }
     93         assertFalse(f.delete());
     94         f.deleteOnExit();
     95         assertFalse(f.exists());
     96         assertEquals("", f.getName());
     97         assertEquals(null, f.getParent());
     98         assertEquals(null, f.getParentFile());
     99         assertEquals("", f.getPath());
    100         assertFalse(f.isAbsolute());
    101         assertFalse(f.isDirectory());
    102         assertFalse(f.isFile());
    103         assertFalse(f.isHidden());
    104         assertEquals(0, f.lastModified());
    105         assertEquals(0, f.length());
    106         assertEquals(null, f.list());
    107         assertEquals(null, f.list(null));
    108         assertEquals(null, f.listFiles());
    109         assertEquals(null, f.listFiles((FileFilter) null));
    110         assertEquals(null, f.listFiles((FilenameFilter) null));
    111         assertFalse(f.mkdir());
    112         assertFalse(f.mkdirs());
    113         assertFalse(f.renameTo(f));
    114         assertFalse(f.setLastModified(123));
    115         assertFalse(f.setExecutable(true));
    116         assertFalse(f.setReadOnly());
    117         assertFalse(f.setReadable(true));
    118         assertFalse(f.setWritable(true));
    119         // ...but sometimes it behaves like "user.dir".
    120         String cwd = System.getProperty("user.dir");
    121         assertEquals(new File(cwd), f.getAbsoluteFile());
    122         assertEquals(cwd, f.getAbsolutePath());
    123         // TODO: how do we test these without hard-coding assumptions about where our temporary
    124         // directory is? (In practice, on Android, our temporary directory is accessed through
    125         // a symbolic link, so the canonical file/path will be different.)
    126         //assertEquals(new File(cwd), f.getCanonicalFile());
    127         //assertEquals(cwd, f.getCanonicalPath());
    128     }
    129 
    130     // http://b/2486943 - between eclair and froyo, we added a call to
    131     // isAbsolute from the File constructor, potentially breaking subclasses.
    132     public void test_subclassing() throws Exception {
    133         class MyFile extends File {
    134             private String field;
    135             MyFile(String s) {
    136                 super(s);
    137                 field = "";
    138             }
    139             @Override public boolean isAbsolute() {
    140                 field.length();
    141                 return super.isAbsolute();
    142             }
    143         }
    144         new MyFile("");
    145     }
    146 
    147     // http://b/3047893 - getCanonicalPath wasn't actually resolving symbolic links.
    148     public void test_getCanonicalPath() throws Exception {
    149         // This assumes you can create symbolic links in the temporary directory. This isn't
    150         // true on Android if you're using /sdcard. It will work in /data/local though.
    151         File base = createTemporaryDirectory();
    152         File target = new File(base, "target");
    153         target.createNewFile(); // The RI won't follow a dangling symlink, which seems like a bug!
    154         File linkName = new File(base, "link");
    155         ln_s(target, linkName);
    156         assertEquals(target.getCanonicalPath(), linkName.getCanonicalPath());
    157 
    158         // .../subdir/shorter -> .../target (using a link to ../target).
    159         File subdir = new File(base, "subdir");
    160         assertTrue(subdir.mkdir());
    161         linkName = new File(subdir, "shorter");
    162         ln_s("../target", linkName.toString());
    163         assertEquals(target.getCanonicalPath(), linkName.getCanonicalPath());
    164 
    165         // .../l -> .../subdir/longer (using a relative link to subdir/longer).
    166         linkName = new File(base, "l");
    167         ln_s("subdir/longer", linkName.toString());
    168         File longer = new File(base, "subdir/longer");
    169         longer.createNewFile(); // The RI won't follow a dangling symlink, which seems like a bug!
    170         assertEquals(longer.getCanonicalPath(), linkName.getCanonicalPath());
    171 
    172         // .../double -> .../target (via a link into subdir and a link back out).
    173         linkName = new File(base, "double");
    174         ln_s("subdir/shorter", linkName.toString());
    175         assertEquals(target.getCanonicalPath(), linkName.getCanonicalPath());
    176     }
    177 
    178     private static void ln_s(File target, File linkName) throws Exception {
    179         ln_s(target.toString(), linkName.toString());
    180     }
    181 
    182     private static void ln_s(String target, String linkName) throws Exception {
    183         Libcore.os.symlink(target, linkName);
    184     }
    185 
    186     public void test_createNewFile() throws Exception {
    187         File f = File.createTempFile("FileTest", "tmp");
    188         assertFalse(f.createNewFile()); // EEXIST -> false
    189         assertFalse(f.getParentFile().createNewFile()); // EEXIST -> false, even if S_ISDIR
    190         try {
    191             new File(f, "poop").createNewFile(); // ENOTDIR -> throw
    192             fail();
    193         } catch (IOException expected) {
    194         }
    195         try {
    196             new File("").createNewFile(); // ENOENT -> throw
    197             fail();
    198         } catch (IOException expected) {
    199         }
    200     }
    201 
    202     public void test_rename() throws Exception {
    203         File f = File.createTempFile("FileTest", "tmp");
    204         assertFalse(f.renameTo(new File("")));
    205         assertFalse(new File("").renameTo(f));
    206         assertFalse(f.renameTo(new File(".")));
    207         assertTrue(f.renameTo(f));
    208     }
    209 
    210     public void test_getAbsolutePath() throws Exception {
    211         String originalUserDir = System.getProperty("user.dir");
    212         try {
    213             File f = new File("poop");
    214             System.setProperty("user.dir", "/a");
    215             assertEquals("/a/poop", f.getAbsolutePath());
    216             System.setProperty("user.dir", "/b");
    217             assertEquals("/b/poop", f.getAbsolutePath());
    218         } finally {
    219             System.setProperty("user.dir", originalUserDir);
    220         }
    221     }
    222 
    223     public void test_getSpace() throws Exception {
    224         assertTrue(new File("/").getFreeSpace() >= 0);
    225         assertTrue(new File("/").getTotalSpace() >= 0);
    226         assertTrue(new File("/").getUsableSpace() >= 0);
    227     }
    228 
    229     public void test_mkdirs() throws Exception {
    230         // Set up a directory to test in.
    231         File base = createTemporaryDirectory();
    232 
    233         // mkdirs returns true only if it _creates_ a directory.
    234         // So we get false for a directory that already exists...
    235         assertTrue(base.exists());
    236         assertFalse(base.mkdirs());
    237         // But true if we had to create something.
    238         File a = new File(base, "a");
    239         assertFalse(a.exists());
    240         assertTrue(a.mkdirs());
    241         assertTrue(a.exists());
    242 
    243         // Test the recursive case where we need to create multiple parents.
    244         File b = new File(a, "b");
    245         File c = new File(b, "c");
    246         File d = new File(c, "d");
    247         assertTrue(a.exists());
    248         assertFalse(b.exists());
    249         assertFalse(c.exists());
    250         assertFalse(d.exists());
    251         assertTrue(d.mkdirs());
    252         assertTrue(a.exists());
    253         assertTrue(b.exists());
    254         assertTrue(c.exists());
    255         assertTrue(d.exists());
    256 
    257         // Test the case where the 'directory' exists as a file.
    258         File existsAsFile = new File(base, "existsAsFile");
    259         existsAsFile.createNewFile();
    260         assertTrue(existsAsFile.exists());
    261         assertFalse(existsAsFile.mkdirs());
    262 
    263         // Test the case where the parent exists as a file.
    264         File badParent = new File(existsAsFile, "sub");
    265         assertTrue(existsAsFile.exists());
    266         assertFalse(badParent.exists());
    267         assertFalse(badParent.mkdirs());
    268     }
    269 }
    270