1 /* 2 * Copyright (C) 2010 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 package com.android.tradefed.util; 17 18 import junit.framework.TestCase; 19 20 import java.io.ByteArrayInputStream; 21 import java.io.File; 22 import java.io.FileInputStream; 23 import java.io.IOException; 24 import java.io.InputStream; 25 import java.util.Collections; 26 import java.util.HashSet; 27 import java.util.Set; 28 29 /** 30 * Functional tests for {@link FileUtil} 31 */ 32 public class FileUtilFuncTest extends TestCase { 33 private static final String PERMS_NONE = "---------"; 34 private static final String PERMS_GRWX = "rwxrwx---"; 35 private static final String DPERMS_NONE = "d" + PERMS_NONE; 36 private static final String DPERMS_GRWX = "d" + PERMS_GRWX; 37 38 private Set<File> mTempFiles = new HashSet<File>(); 39 40 @Override tearDown()41 protected void tearDown() throws Exception { 42 super.tearDown(); 43 for (File file : mTempFiles) { 44 if (file != null && file.exists()) { 45 if (file.isDirectory()) { 46 FileUtil.recursiveDelete(file); 47 } else { 48 file.delete(); 49 } 50 } 51 } 52 } 53 54 /** 55 * Make sure that {@link FileUtil#mkdirsRWX} works when there are multiple levels of directories 56 */ testMkdirsRWX_multiLevel()57 public void testMkdirsRWX_multiLevel() throws IOException { 58 final int subdirCount = 5; 59 File tmpParentDir = createTempDir("foo"); 60 // create a hierarchy of directories to be created 61 File[] subdirs = new File[subdirCount]; 62 subdirs[0] = new File(tmpParentDir, "patient0"); 63 for (int i = 1; i < subdirCount; i++) { 64 subdirs[i] = new File(subdirs[i - 1], String.format("subdir%d", i)); 65 } 66 assertFalse(subdirs[0].exists()); 67 FileUtil.mkdirsRWX(subdirs[subdirs.length - 1]); 68 69 for (int i = 0; i < subdirCount; i++) { 70 assertTrue(subdirs[i].exists()); 71 assertUnixPerms(subdirs[i], DPERMS_GRWX); 72 } 73 } 74 75 /** 76 * Make sure that {@link FileUtil#mkdirsRWX} works in the basic case 77 */ testMkdirsRWX_singleLevel()78 public void testMkdirsRWX_singleLevel() throws IOException { 79 File tmpParentDir = createTempDir("foo"); 80 File subdir = new File(tmpParentDir, "subdirectory"); 81 assertFalse(subdir.exists()); 82 FileUtil.mkdirsRWX(subdir); 83 assertTrue(subdir.exists()); 84 assertUnixPerms(subdir, DPERMS_GRWX); 85 } 86 87 /** 88 * Make sure that {@link FileUtil#mkdirsRWX} works when the directory to be touched already 89 * exists 90 */ testMkdirsRWX_preExisting()91 public void testMkdirsRWX_preExisting() throws IOException { 92 File tmpParentDir = createTempDir("foo"); 93 File subdir = new File(tmpParentDir, "subdirectory"); 94 subdir.mkdir(); 95 subdir.setExecutable(false, false); 96 subdir.setReadable(false, false); 97 subdir.setWritable(false, false); 98 99 assertUnixPerms(subdir, DPERMS_NONE); 100 FileUtil.mkdirsRWX(subdir); 101 assertTrue(subdir.exists()); 102 assertUnixPerms(subdir, DPERMS_GRWX); 103 } 104 105 /** 106 * Simple test for {@link FileUtil#chmodGroupRW(File)}. 107 */ testChmodGroupRW()108 public void testChmodGroupRW() throws IOException { 109 File tmpFile = createTempFile("foo", "txt"); 110 tmpFile.setReadable(false); 111 tmpFile.setWritable(false); 112 FileUtil.chmodGroupRW(tmpFile); 113 assertTrue(tmpFile.canRead()); 114 assertTrue(tmpFile.canWrite()); 115 } 116 117 /** 118 * Simple test for {@link FileUtil#createTempDir(String)}. 119 */ testCreateTempDir()120 public void testCreateTempDir() throws IOException { 121 File tmpDir = createTempDir("foo"); 122 assertTrue(tmpDir.exists()); 123 assertTrue(tmpDir.isDirectory()); 124 } 125 126 /** 127 * Simple test for {@link FileUtil#createTempDir(String, File)}. 128 */ testCreateTempDir_parentFile()129 public void testCreateTempDir_parentFile() throws IOException { 130 File tmpParentDir = createTempDir("foo"); 131 File childDir = createTempDir("foochild", tmpParentDir); 132 assertTrue(childDir.exists()); 133 assertTrue(childDir.isDirectory()); 134 assertEquals(tmpParentDir.getAbsolutePath(), childDir.getParent()); 135 } 136 137 /** 138 * Simple test for {@link FileUtil#createTempFile(String, String)}. 139 */ testCreateTempFile()140 public void testCreateTempFile() throws IOException { 141 File tmpFile = createTempFile("foo", ".txt"); 142 assertTrue(tmpFile.exists()); 143 assertTrue(tmpFile.isFile()); 144 assertTrue(tmpFile.getName().startsWith("foo")); 145 assertTrue(tmpFile.getName().endsWith(".txt")); 146 } 147 148 /** 149 * Simple test for {@link FileUtil#createTempFile(String, String, File)}. 150 */ testCreateTempFile_parentDir()151 public void testCreateTempFile_parentDir() throws IOException { 152 File tmpParentDir = createTempDir("foo"); 153 154 File tmpFile = createTempFile("foo", ".txt", tmpParentDir); 155 assertTrue(tmpFile.exists()); 156 assertTrue(tmpFile.isFile()); 157 assertTrue(tmpFile.getName().startsWith("foo")); 158 assertTrue(tmpFile.getName().endsWith(".txt")); 159 assertEquals(tmpParentDir.getAbsolutePath(), tmpFile.getParent()); 160 } 161 162 /** 163 * Simple test method for {@link FileUtil#writeToFile(InputStream, File)}. 164 */ testWriteToFile()165 public void testWriteToFile() throws IOException { 166 final String testContents = "this is the temp file test data"; 167 InputStream input = new ByteArrayInputStream(testContents.getBytes()); 168 File tmpFile = createTempFile("foo", ".txt"); 169 FileUtil.writeToFile(input, tmpFile); 170 String readContents = StreamUtil.getStringFromStream(new FileInputStream(tmpFile)); 171 assertEquals(testContents, readContents); 172 } 173 testRecursiveDelete()174 public void testRecursiveDelete() throws IOException { 175 File tmpParentDir = createTempDir("foo"); 176 File childDir = createTempDir("foochild", tmpParentDir); 177 File subFile = createTempFile("foo", ".txt", childDir); 178 FileUtil.recursiveDelete(tmpParentDir); 179 assertFalse(subFile.exists()); 180 assertFalse(childDir.exists()); 181 assertFalse(tmpParentDir.exists()); 182 } 183 184 /** 185 * Test {@link FileUtil#recursiveCopy(File, File)} to recursively copy a directory to an 186 * existing, empty directory. 187 */ testRecursiveCopy()188 public void testRecursiveCopy() throws IOException { 189 // create source tree 190 File tmpParentDir = createTempDir("foo"); 191 File childDir = createTempDir("foochild", tmpParentDir); 192 File subFile = createTempFile("foo", ".txt", childDir); 193 FileUtil.writeToFile("foo", subFile); 194 // create empty destination directory 195 File destDir = createTempDir("dest"); 196 // invoke target method 197 FileUtil.recursiveCopy(tmpParentDir, destDir); 198 // check tree was copied 199 File subFileCopy = new File(destDir, String.format("%s%s%s", childDir.getName(), 200 File.separator, subFile.getName())); 201 assertTrue(subFileCopy.exists()); 202 assertTrue(FileUtil.compareFileContents(subFile, subFileCopy)); 203 } 204 205 /** 206 * Test {@link FileUtil#recursiveCopy(File, File)} to recursively copy a directory to a 207 * directory that does not exist. 208 */ testRecursiveCopyToNonexistentTarget()209 public void testRecursiveCopyToNonexistentTarget() throws IOException { 210 // create source tree 211 File tmpParentDir = createTempDir("foo"); 212 File childDir = createTempDir("foochild", tmpParentDir); 213 File subFile = createTempFile("foo", ".txt", childDir); 214 FileUtil.writeToFile("foo", subFile); 215 // generate an unique name for destination dir and make sure it doesn't exist 216 File destDir = createTempDir("dest"); 217 assertTrue(destDir.delete()); 218 assertFalse(destDir.exists()); 219 // invoke target method 220 FileUtil.recursiveCopy(tmpParentDir, destDir); 221 // check that destination was created and tree was copied 222 File subFileCopy = new File(destDir, String.format("%s%s%s", childDir.getName(), 223 File.separator, subFile.getName())); 224 assertTrue(destDir.exists()); 225 assertTrue(subFileCopy.exists()); 226 assertTrue(FileUtil.compareFileContents(subFile, subFileCopy)); 227 } 228 testFindDirsUnder()229 public void testFindDirsUnder() throws IOException { 230 File absRootDir = createTempDir("rootDir"); 231 File relRootDir = new File(absRootDir.getName()); 232 File absSubDir1 = createTempDir("subdir1", absRootDir); 233 File relSubDir1 = new File(relRootDir.getName(), absSubDir1.getName()); 234 File absSubDir2 = createTempDir("subdir2", absRootDir); 235 File relSubDir2 = new File(relRootDir.getName(), absSubDir2.getName()); 236 File aFile = createTempFile("aFile", ".txt", absSubDir2); 237 238 HashSet<File> expected = new HashSet<File>(); 239 Collections.addAll(expected, relRootDir, relSubDir1, relSubDir2); 240 assertEquals(expected, FileUtil.findDirsUnder(absRootDir, null)); 241 expected.clear(); 242 File fakeRoot = new File("fakeRoot"); 243 Collections.addAll(expected, 244 new File(fakeRoot, relRootDir.getPath()), 245 new File(fakeRoot, relSubDir1.getPath()), 246 new File(fakeRoot, relSubDir2.getPath())); 247 assertEquals("Failed to apply a new relative parent", expected, 248 FileUtil.findDirsUnder(absRootDir, fakeRoot)); 249 assertEquals("found something when passing null as a root dir", 0, 250 FileUtil.findDirsUnder(null, null).size()); 251 try { 252 FileUtil.findDirsUnder(aFile, null); 253 fail("should have thrown an excpetion when passing in something that's not a dir"); 254 } catch (IllegalArgumentException e) { 255 assertTrue(true); 256 } 257 } 258 259 /** 260 * Test method for {@link FileUtil#createTempFileForRemote(String, File)}. 261 */ testCreateTempFileForRemote()262 public void testCreateTempFileForRemote() throws IOException { 263 String remoteFilePath = "path/userdata.img"; 264 File tmpFile = FileUtil.createTempFileForRemote(remoteFilePath, null); 265 try { 266 assertTrue(tmpFile.getAbsolutePath().contains("userdata")); 267 assertTrue(tmpFile.getAbsolutePath().endsWith(".img")); 268 } finally { 269 FileUtil.deleteFile(tmpFile); 270 } 271 } 272 273 /** 274 * Test method for {@link FileUtil#createTempFileForRemote(String, File)} for a nested path. 275 */ testCreateTempFileForRemote_nested()276 public void testCreateTempFileForRemote_nested() throws IOException { 277 String remoteFilePath = "path/2path/userdata.img"; 278 File tmpFile = FileUtil.createTempFileForRemote(remoteFilePath, null); 279 try { 280 assertTrue(tmpFile.getAbsolutePath().contains("userdata")); 281 assertTrue(tmpFile.getAbsolutePath().endsWith(".img")); 282 } finally { 283 FileUtil.deleteFile(tmpFile); 284 } 285 } 286 287 /** 288 * Test {@link FileUtil#createTempFileForRemote(String, File)} for file with no extension 289 */ testCreateTempFileForRemote_noext()290 public void testCreateTempFileForRemote_noext() throws IOException { 291 String remoteFilePath = "path/2path/userddddmg"; 292 File tmpFile = FileUtil.createTempFileForRemote(remoteFilePath, null); 293 try { 294 assertTrue(tmpFile.getAbsolutePath().contains("userddddmg")); 295 } finally { 296 FileUtil.deleteFile(tmpFile); 297 } 298 } 299 300 /** 301 * Test {@link FileUtil#createTempFileForRemote(String, File)} for a too small prefix. 302 */ testCreateTempFileForRemote_short()303 public void testCreateTempFileForRemote_short() throws IOException { 304 String remoteFilePath = "path/2path/us.img"; 305 File tmpFile = FileUtil.createTempFileForRemote(remoteFilePath, null); 306 try { 307 assertTrue(tmpFile.getAbsolutePath().contains("usXXX")); 308 assertTrue(tmpFile.getAbsolutePath().endsWith(".img")); 309 } finally { 310 FileUtil.deleteFile(tmpFile); 311 } 312 } 313 314 /** 315 * Test {@link FileUtil#createTempFileForRemote(String, File)} for remoteFile in root path. 316 */ testCreateTempFileForRemote_singleFile()317 public void testCreateTempFileForRemote_singleFile() throws IOException { 318 String remoteFilePath = "userdata.img"; 319 File tmpFile = FileUtil.createTempFileForRemote(remoteFilePath, null); 320 try { 321 assertTrue(tmpFile.getAbsolutePath().contains("userdata")); 322 assertTrue(tmpFile.getAbsolutePath().endsWith(".img")); 323 } finally { 324 FileUtil.deleteFile(tmpFile); 325 } 326 } 327 328 /** 329 * Verify {@link FileUtil#calculateMd5(File)} works. 330 * @throws IOException 331 */ testCalculateMd5()332 public void testCalculateMd5() throws IOException { 333 final String source = "testtesttesttesttest"; 334 final String md5 = "f317f682fafe0309c6a423af0b4efa59"; 335 File tmpFile = FileUtil.createTempFile("testCalculateMd5", ".txt"); 336 try { 337 FileUtil.writeToFile(source, tmpFile); 338 String actualMd5 = FileUtil.calculateMd5(tmpFile); 339 assertEquals(md5, actualMd5); 340 } finally { 341 FileUtil.deleteFile(tmpFile); 342 } 343 } 344 345 /** Test that {@link FileUtil#recursiveSymlink(File, File)} properly simlink files. */ testRecursiveSymlink()346 public void testRecursiveSymlink() throws IOException { 347 File dir1 = null; 348 File dest = null; 349 try { 350 dir1 = FileUtil.createTempDir("orig-dir"); 351 File subdir1 = FileUtil.createTempDir("sub-dir", dir1); 352 File testFile = FileUtil.createTempFile("test", "file", subdir1); 353 dest = FileUtil.createTempDir("dest-dir"); 354 FileUtil.recursiveSymlink(dir1, dest); 355 // check that file is in dest dir 356 assertNotNull(FileUtil.findFile(dest, testFile.getName())); 357 } finally { 358 FileUtil.recursiveDelete(dir1); 359 FileUtil.recursiveDelete(dest); 360 } 361 } 362 363 /** 364 * Test that when a symlink dir is encountered by {@link FileUtil#recursiveDelete(File)}. The 365 * link itself is deleted but not followed. 366 */ testSymlinkDeletion()367 public void testSymlinkDeletion() throws IOException { 368 File dir1 = null; 369 File dest = null; 370 try { 371 dir1 = FileUtil.createTempDir("orig-dir"); 372 File subdir1 = FileUtil.createTempDir("sub-dir", dir1); 373 File testFile = FileUtil.createTempFile("test", "file", subdir1); 374 dest = FileUtil.createTempDir("dest-dir"); 375 dest.delete(); 376 FileUtil.symlinkFile(dir1, dest); 377 // Check that file is in dest dir 378 assertNotNull(FileUtil.findFile(dest, testFile.getName())); 379 // Now delete the symlink 380 FileUtil.recursiveDelete(dest); 381 assertFalse(dest.exists()); 382 // Ensure the orignal directory was not deleted (symlink was not followed). 383 assertTrue(subdir1.exists()); 384 } finally { 385 FileUtil.recursiveDelete(dir1); 386 FileUtil.recursiveDelete(dest); 387 } 388 } 389 390 // Assertions assertUnixPerms(File file, String expPerms)391 private String assertUnixPerms(File file, String expPerms) { 392 String perms = ls(file.getPath()); 393 assertTrue(String.format("Expected file %s perms to be '%s' but they were '%s'.", file, 394 expPerms, perms), perms.startsWith(expPerms)); 395 return perms; 396 } 397 398 // Helpers ls(String path)399 private String ls(String path) { 400 CommandResult result = 401 RunUtil.getDefault().runTimedCmdRetry(10 * 1000, 0, 3, "ls", "-ld", path); 402 return result.getStdout(); 403 } 404 createTempDir(String prefix)405 private File createTempDir(String prefix) throws IOException { 406 return createTempDir(prefix, null); 407 } 408 createTempDir(String prefix, File parentDir)409 private File createTempDir(String prefix, File parentDir) throws IOException { 410 File tempDir = FileUtil.createTempDir(prefix, parentDir); 411 mTempFiles.add(tempDir); 412 return tempDir; 413 } 414 createTempFile(String prefix, String suffix)415 private File createTempFile(String prefix, String suffix) throws IOException { 416 File tempFile = FileUtil.createTempFile(prefix, suffix); 417 mTempFiles.add(tempFile); 418 return tempFile; 419 } 420 createTempFile(String prefix, String suffix, File parentDir)421 private File createTempFile(String prefix, String suffix, File parentDir) throws IOException { 422 File tempFile = FileUtil.createTempFile(prefix, suffix, parentDir); 423 mTempFiles.add(tempFile); 424 return tempFile; 425 } 426 } 427