Home | History | Annotate | Download | only in util
      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
     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      */
     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      */
     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      */
     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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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 
    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      */
    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      */
    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 
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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#recursiveSimlink(File, File)} properly simlink files. */
    346     public void testRecursiveSimlink() 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.recursiveSimlink(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     // Assertions
    364     private String assertUnixPerms(File file, String expPerms) {
    365         String perms = ls(file.getPath());
    366         assertTrue(String.format("Expected file %s perms to be '%s' but they were '%s'.", file,
    367                 expPerms, perms), perms.startsWith(expPerms));
    368         return perms;
    369     }
    370 
    371     // Helpers
    372     private String ls(String path) {
    373         CommandResult result =
    374                 RunUtil.getDefault().runTimedCmdRetry(10 * 1000, 0, 3, "ls", "-ld", path);
    375         return result.getStdout();
    376     }
    377 
    378     private File createTempDir(String prefix) throws IOException {
    379         return createTempDir(prefix, null);
    380     }
    381 
    382     private File createTempDir(String prefix, File parentDir) throws IOException {
    383         File tempDir = FileUtil.createTempDir(prefix, parentDir);
    384         mTempFiles.add(tempDir);
    385         return tempDir;
    386     }
    387 
    388     private File createTempFile(String prefix, String suffix) throws IOException {
    389         File tempFile = FileUtil.createTempFile(prefix, suffix);
    390         mTempFiles.add(tempFile);
    391         return tempFile;
    392     }
    393 
    394     private File createTempFile(String prefix, String suffix, File parentDir) throws IOException {
    395         File tempFile = FileUtil.createTempFile(prefix, suffix, parentDir);
    396         mTempFiles.add(tempFile);
    397         return tempFile;
    398     }
    399 }
    400