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