1 /* 2 * Copyright (C) 2008 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 android.os; 18 19 import static android.text.format.DateUtils.DAY_IN_MILLIS; 20 import static android.text.format.DateUtils.HOUR_IN_MILLIS; 21 import static android.text.format.DateUtils.WEEK_IN_MILLIS; 22 23 import android.content.Context; 24 import android.test.AndroidTestCase; 25 import android.test.suitebuilder.annotation.MediumTest; 26 27 import com.google.android.collect.Sets; 28 29 import libcore.io.IoUtils; 30 31 import java.io.ByteArrayInputStream; 32 import java.io.File; 33 import java.io.FileOutputStream; 34 import java.io.FileWriter; 35 import java.util.Arrays; 36 import java.util.HashSet; 37 38 @MediumTest 39 public class FileUtilsTest extends AndroidTestCase { 40 private static final String TEST_DATA = 41 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 42 43 private File mDir; 44 private File mTestFile; 45 private File mCopyFile; 46 47 @Override 48 protected void setUp() throws Exception { 49 super.setUp(); 50 mDir = getContext().getDir("testing", Context.MODE_PRIVATE); 51 mTestFile = new File(mDir, "test.file"); 52 mCopyFile = new File(mDir, "copy.file"); 53 } 54 55 @Override 56 protected void tearDown() throws Exception { 57 IoUtils.deleteContents(mDir); 58 } 59 60 // TODO: test setPermissions(), getPermissions() 61 62 public void testCopyFile() throws Exception { 63 stageFile(mTestFile, TEST_DATA); 64 assertFalse(mCopyFile.exists()); 65 FileUtils.copyFile(mTestFile, mCopyFile); 66 assertTrue(mCopyFile.exists()); 67 assertEquals(TEST_DATA, FileUtils.readTextFile(mCopyFile, 0, null)); 68 } 69 70 public void testCopyToFile() throws Exception { 71 final String s = "Foo Bar"; 72 assertFalse(mCopyFile.exists()); 73 FileUtils.copyToFile(new ByteArrayInputStream(s.getBytes()), mCopyFile); 74 assertTrue(mCopyFile.exists()); 75 assertEquals(s, FileUtils.readTextFile(mCopyFile, 0, null)); 76 } 77 78 public void testIsFilenameSafe() throws Exception { 79 assertTrue(FileUtils.isFilenameSafe(new File("foobar"))); 80 assertTrue(FileUtils.isFilenameSafe(new File("a_b-c=d.e/0,1+23"))); 81 assertFalse(FileUtils.isFilenameSafe(new File("foo*bar"))); 82 assertFalse(FileUtils.isFilenameSafe(new File("foo\nbar"))); 83 } 84 85 public void testReadTextFile() throws Exception { 86 stageFile(mTestFile, TEST_DATA); 87 88 assertEquals(TEST_DATA, FileUtils.readTextFile(mTestFile, 0, null)); 89 90 assertEquals("ABCDE", FileUtils.readTextFile(mTestFile, 5, null)); 91 assertEquals("ABCDE<>", FileUtils.readTextFile(mTestFile, 5, "<>")); 92 assertEquals(TEST_DATA.substring(0, 51) + "<>", 93 FileUtils.readTextFile(mTestFile, 51, "<>")); 94 assertEquals(TEST_DATA, FileUtils.readTextFile(mTestFile, 52, "<>")); 95 assertEquals(TEST_DATA, FileUtils.readTextFile(mTestFile, 100, "<>")); 96 97 assertEquals("vwxyz", FileUtils.readTextFile(mTestFile, -5, null)); 98 assertEquals("<>vwxyz", FileUtils.readTextFile(mTestFile, -5, "<>")); 99 assertEquals("<>" + TEST_DATA.substring(1, 52), 100 FileUtils.readTextFile(mTestFile, -51, "<>")); 101 assertEquals(TEST_DATA, FileUtils.readTextFile(mTestFile, -52, "<>")); 102 assertEquals(TEST_DATA, FileUtils.readTextFile(mTestFile, -100, "<>")); 103 } 104 105 public void testReadTextFileWithZeroLengthFile() throws Exception { 106 stageFile(mTestFile, TEST_DATA); 107 new FileOutputStream(mTestFile).close(); // Zero out the file 108 assertEquals("", FileUtils.readTextFile(mTestFile, 0, null)); 109 assertEquals("", FileUtils.readTextFile(mTestFile, 1, "<>")); 110 assertEquals("", FileUtils.readTextFile(mTestFile, 10, "<>")); 111 assertEquals("", FileUtils.readTextFile(mTestFile, -1, "<>")); 112 assertEquals("", FileUtils.readTextFile(mTestFile, -10, "<>")); 113 } 114 115 public void testContains() throws Exception { 116 assertTrue(FileUtils.contains(new File("/"), new File("/moo.txt"))); 117 assertTrue(FileUtils.contains(new File("/"), new File("/"))); 118 119 assertTrue(FileUtils.contains(new File("/sdcard"), new File("/sdcard"))); 120 assertTrue(FileUtils.contains(new File("/sdcard/"), new File("/sdcard/"))); 121 122 assertTrue(FileUtils.contains(new File("/sdcard"), new File("/sdcard/moo.txt"))); 123 assertTrue(FileUtils.contains(new File("/sdcard/"), new File("/sdcard/moo.txt"))); 124 125 assertFalse(FileUtils.contains(new File("/sdcard"), new File("/moo.txt"))); 126 assertFalse(FileUtils.contains(new File("/sdcard/"), new File("/moo.txt"))); 127 128 assertFalse(FileUtils.contains(new File("/sdcard"), new File("/sdcard.txt"))); 129 assertFalse(FileUtils.contains(new File("/sdcard/"), new File("/sdcard.txt"))); 130 } 131 132 public void testDeleteOlderEmptyDir() throws Exception { 133 FileUtils.deleteOlderFiles(mDir, 10, WEEK_IN_MILLIS); 134 assertDirContents(); 135 } 136 137 public void testDeleteOlderTypical() throws Exception { 138 touch("file1", HOUR_IN_MILLIS); 139 touch("file2", 1 * DAY_IN_MILLIS + HOUR_IN_MILLIS); 140 touch("file3", 2 * DAY_IN_MILLIS + HOUR_IN_MILLIS); 141 touch("file4", 3 * DAY_IN_MILLIS + HOUR_IN_MILLIS); 142 touch("file5", 4 * DAY_IN_MILLIS + HOUR_IN_MILLIS); 143 assertTrue(FileUtils.deleteOlderFiles(mDir, 3, DAY_IN_MILLIS)); 144 assertDirContents("file1", "file2", "file3"); 145 } 146 147 public void testDeleteOlderInFuture() throws Exception { 148 touch("file1", -HOUR_IN_MILLIS); 149 touch("file2", HOUR_IN_MILLIS); 150 touch("file3", WEEK_IN_MILLIS); 151 assertTrue(FileUtils.deleteOlderFiles(mDir, 0, DAY_IN_MILLIS)); 152 assertDirContents("file1", "file2"); 153 154 touch("file1", -HOUR_IN_MILLIS); 155 touch("file2", HOUR_IN_MILLIS); 156 touch("file3", WEEK_IN_MILLIS); 157 assertTrue(FileUtils.deleteOlderFiles(mDir, 0, DAY_IN_MILLIS)); 158 assertDirContents("file1", "file2"); 159 } 160 161 public void testDeleteOlderOnlyAge() throws Exception { 162 touch("file1", HOUR_IN_MILLIS); 163 touch("file2", 1 * DAY_IN_MILLIS + HOUR_IN_MILLIS); 164 touch("file3", 2 * DAY_IN_MILLIS + HOUR_IN_MILLIS); 165 touch("file4", 3 * DAY_IN_MILLIS + HOUR_IN_MILLIS); 166 touch("file5", 4 * DAY_IN_MILLIS + HOUR_IN_MILLIS); 167 assertTrue(FileUtils.deleteOlderFiles(mDir, 0, DAY_IN_MILLIS)); 168 assertFalse(FileUtils.deleteOlderFiles(mDir, 0, DAY_IN_MILLIS)); 169 assertDirContents("file1"); 170 } 171 172 public void testDeleteOlderOnlyCount() throws Exception { 173 touch("file1", HOUR_IN_MILLIS); 174 touch("file2", 1 * DAY_IN_MILLIS + HOUR_IN_MILLIS); 175 touch("file3", 2 * DAY_IN_MILLIS + HOUR_IN_MILLIS); 176 touch("file4", 3 * DAY_IN_MILLIS + HOUR_IN_MILLIS); 177 touch("file5", 4 * DAY_IN_MILLIS + HOUR_IN_MILLIS); 178 assertTrue(FileUtils.deleteOlderFiles(mDir, 2, 0)); 179 assertFalse(FileUtils.deleteOlderFiles(mDir, 2, 0)); 180 assertDirContents("file1", "file2"); 181 } 182 183 public void testValidExtFilename() throws Exception { 184 assertTrue(FileUtils.isValidExtFilename("a")); 185 assertTrue(FileUtils.isValidExtFilename("foo.bar")); 186 assertTrue(FileUtils.isValidExtFilename("foo bar.baz")); 187 assertTrue(FileUtils.isValidExtFilename("foo.bar.baz")); 188 assertTrue(FileUtils.isValidExtFilename(".bar")); 189 assertTrue(FileUtils.isValidExtFilename("foo~!@#$%^&*()_[]{}+bar")); 190 191 assertFalse(FileUtils.isValidExtFilename(null)); 192 assertFalse(FileUtils.isValidExtFilename(".")); 193 assertFalse(FileUtils.isValidExtFilename("../foo")); 194 assertFalse(FileUtils.isValidExtFilename("/foo")); 195 196 assertEquals(".._foo", FileUtils.buildValidExtFilename("../foo")); 197 assertEquals("_foo", FileUtils.buildValidExtFilename("/foo")); 198 assertEquals("foo_bar", FileUtils.buildValidExtFilename("foo\0bar")); 199 assertEquals(".foo", FileUtils.buildValidExtFilename(".foo")); 200 assertEquals("foo.bar", FileUtils.buildValidExtFilename("foo.bar")); 201 } 202 203 public void testValidFatFilename() throws Exception { 204 assertTrue(FileUtils.isValidFatFilename("a")); 205 assertTrue(FileUtils.isValidFatFilename("foo bar.baz")); 206 assertTrue(FileUtils.isValidFatFilename("foo.bar.baz")); 207 assertTrue(FileUtils.isValidFatFilename(".bar")); 208 assertTrue(FileUtils.isValidFatFilename("foo.bar")); 209 assertTrue(FileUtils.isValidFatFilename("foo bar")); 210 assertTrue(FileUtils.isValidFatFilename("foo+bar")); 211 assertTrue(FileUtils.isValidFatFilename("foo,bar")); 212 213 assertFalse(FileUtils.isValidFatFilename("foo*bar")); 214 assertFalse(FileUtils.isValidFatFilename("foo?bar")); 215 assertFalse(FileUtils.isValidFatFilename("foo<bar")); 216 assertFalse(FileUtils.isValidFatFilename(null)); 217 assertFalse(FileUtils.isValidFatFilename(".")); 218 assertFalse(FileUtils.isValidFatFilename("../foo")); 219 assertFalse(FileUtils.isValidFatFilename("/foo")); 220 221 assertEquals(".._foo", FileUtils.buildValidFatFilename("../foo")); 222 assertEquals("_foo", FileUtils.buildValidFatFilename("/foo")); 223 assertEquals(".foo", FileUtils.buildValidFatFilename(".foo")); 224 assertEquals("foo.bar", FileUtils.buildValidFatFilename("foo.bar")); 225 assertEquals("foo_bar__baz", FileUtils.buildValidFatFilename("foo?bar**baz")); 226 } 227 228 private void touch(String name, long age) throws Exception { 229 final File file = new File(mDir, name); 230 file.createNewFile(); 231 file.setLastModified(System.currentTimeMillis() - age); 232 } 233 234 private void stageFile(File file, String data) throws Exception { 235 FileWriter writer = new FileWriter(file); 236 try { 237 writer.write(data, 0, data.length()); 238 } finally { 239 writer.close(); 240 } 241 } 242 243 private void assertDirContents(String... expected) { 244 final HashSet<String> expectedSet = Sets.newHashSet(expected); 245 String[] actual = mDir.list(); 246 if (actual == null) actual = new String[0]; 247 248 assertEquals( 249 "Expected " + Arrays.toString(expected) + " but actual " + Arrays.toString(actual), 250 expected.length, actual.length); 251 for (String actualFile : actual) { 252 assertTrue("Unexpected actual file " + actualFile, expectedSet.contains(actualFile)); 253 } 254 } 255 } 256