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