Home | History | Annotate | Download | only in io
      1 /*
      2  * Copyright (C) 2009 The Guava Authors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
      5  * use this file except in compliance with the License.  You may obtain a copy
      6  * 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, WITHOUT
     12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
     13  * License for the specific language governing permissions and limitations under
     14  * the License.
     15  */
     16 
     17 package com.google.common.io;
     18 
     19 import static com.google.common.base.Charsets.UTF_8;
     20 import static com.google.common.io.Files.simplifyPath;
     21 
     22 import com.google.common.base.CharMatcher;
     23 import com.google.common.base.Splitter;
     24 
     25 import junit.framework.TestCase;
     26 
     27 import java.io.IOException;
     28 import java.net.URL;
     29 import java.util.Iterator;
     30 
     31 /**
     32  * Unit tests for {@link Files#simplifyPath}.
     33  *
     34  * @author Pablo Bellver
     35  */
     36 public class FilesSimplifyPathTest extends TestCase {
     37 
     38   public void testSimplifyEmptyString() {
     39     assertEquals(".", simplifyPath(""));
     40   }
     41 
     42   public void testSimplifyDot() {
     43     assertEquals(".", simplifyPath("."));
     44   }
     45 
     46   public void testSimplifyWhiteSpace() {
     47     assertEquals(" ", simplifyPath(" "));
     48   }
     49 
     50   public void testSimplify2() {
     51     assertEquals("x", simplifyPath("x"));
     52   }
     53 
     54   public void testSimplify3() {
     55     assertEquals("/a/b/c/d", simplifyPath("/a/b/c/d"));
     56   }
     57 
     58   public void testSimplify4() {
     59     assertEquals("/a/b/c/d", simplifyPath("/a/b/c/d/"));
     60   }
     61 
     62   public void testSimplify5() {
     63     assertEquals("/a/b", simplifyPath("/a//b"));
     64   }
     65 
     66   public void testSimplify6() {
     67     assertEquals("/a/b", simplifyPath("//a//b/"));
     68   }
     69 
     70   public void testSimplify7() {
     71     assertEquals("/", simplifyPath("/.."));
     72   }
     73 
     74   public void testSimplify8() {
     75     assertEquals("/", simplifyPath("/././././"));
     76   }
     77 
     78   public void testSimplify9() {
     79     assertEquals("/a", simplifyPath("/a/b/.."));
     80   }
     81 
     82   public void testSimplify10() {
     83     assertEquals("/", simplifyPath("/a/b/../../.."));
     84   }
     85 
     86   public void testSimplify11() {
     87     assertEquals("/", simplifyPath("//a//b/..////../..//"));
     88   }
     89 
     90   public void testSimplify12() {
     91     assertEquals("/x", simplifyPath("//a//../x//"));
     92   }
     93 
     94   public void testSimplify13() {
     95     assertEquals("../c", simplifyPath("a/b/../../../c"));
     96   }
     97 
     98   public void testSimplifyDotDot() {
     99     assertEquals("..", simplifyPath(".."));
    100   }
    101 
    102   public void testSimplifyDotDotSlash() {
    103     assertEquals("..", simplifyPath("../"));
    104     assertEquals("..", simplifyPath("a/../.."));
    105     assertEquals("..", simplifyPath("a/../../"));
    106   }
    107 
    108   public void testSimplifyDotDots() {
    109     assertEquals("../..", simplifyPath("a/../../.."));
    110     assertEquals("../../..", simplifyPath("a/../../../.."));
    111   }
    112 
    113   public void testSimplifyRootedDotDots() {
    114     assertEquals("/", simplifyPath("/../../.."));
    115     assertEquals("/", simplifyPath("/../../../"));
    116   }
    117 
    118   // b/4558855
    119   public void testMadbotsBug() {
    120     assertEquals("../this", simplifyPath("../this"));
    121     assertEquals("../this/is/ok", simplifyPath("../this/is/ok"));
    122     assertEquals("../ok", simplifyPath("../this/../ok"));
    123   }
    124 
    125   // https://code.google.com/p/guava-libraries/issues/detail?id=705
    126   public void test705() {
    127     assertEquals("../b", simplifyPath("x/../../b"));
    128     assertEquals("b", simplifyPath("x/../b"));
    129   }
    130 
    131   // https://code.google.com/p/guava-libraries/issues/detail?id=716
    132   public void test716() {
    133     assertEquals("b", simplifyPath("./b"));
    134     assertEquals("b", simplifyPath("./b/."));
    135     assertEquals("b", simplifyPath("././b/./."));
    136     assertEquals("b", simplifyPath("././b"));
    137     assertEquals("a/b", simplifyPath("./a/b"));
    138   }
    139 
    140   public void testHiddenFiles() {
    141     assertEquals(".b", simplifyPath(".b"));
    142     assertEquals(".b", simplifyPath("./.b"));
    143     assertEquals(".metadata/b", simplifyPath(".metadata/b"));
    144     assertEquals(".metadata/b", simplifyPath("./.metadata/b"));
    145   }
    146 
    147   // https://code.google.com/p/guava-libraries/issues/detail?id=716
    148   public void testMultipleDotFilenames() {
    149     assertEquals("..a", simplifyPath("..a"));
    150     assertEquals("/..a", simplifyPath("/..a"));
    151     assertEquals("/..a/..b", simplifyPath("/..a/..b"));
    152     assertEquals("/.....a/..b", simplifyPath("/.....a/..b"));
    153     assertEquals("..../....", simplifyPath("..../...."));
    154     assertEquals("..a../..b..", simplifyPath("..a../..b.."));
    155   }
    156 
    157   public void testSlashDot() {
    158     assertEquals("/", simplifyPath("/."));
    159   }
    160 
    161   // http://code.google.com/p/guava-libraries/issues/detail?id=722
    162   public void testInitialSlashDotDot() {
    163     assertEquals("/c", simplifyPath("/../c"));
    164   }
    165 
    166   // http://code.google.com/p/guava-libraries/issues/detail?id=722
    167   public void testInitialSlashDot() {
    168     assertEquals("/a", simplifyPath("/./a"));
    169     assertEquals("/.a", simplifyPath("/.a/a/.."));
    170   }
    171 
    172   // http://code.google.com/p/guava-libraries/issues/detail?id=722
    173   public void testConsecutiveParentsAfterPresent() {
    174     assertEquals("../..", simplifyPath("./../../"));
    175     assertEquals("../..", simplifyPath("./.././../"));
    176   }
    177 
    178   /*
    179    * We co-opt some URI resolution tests for our purposes.
    180    * Some of the tests have queries and anchors that are a little silly here.
    181    */
    182 
    183   /** http://gbiv.com/protocols/uri/rfc/rfc2396.html#rfc.section.C.1 */
    184   public void testRfc2396Normal() {
    185     assertEquals("/a/b/c/g", simplifyPath("/a/b/c/g"));
    186     assertEquals("/a/b/c/g", simplifyPath("/a/b/c/./g"));
    187     assertEquals("/a/b/c/g", simplifyPath("/a/b/c/g/"));
    188 
    189     assertEquals("/a/b/c/g?y", simplifyPath("/a/b/c/g?y"));
    190     assertEquals("/a/b/c/g#s", simplifyPath("/a/b/c/g#s"));
    191     assertEquals("/a/b/c/g?y#s", simplifyPath("/a/b/c/g?y#s"));
    192     assertEquals("/a/b/c/;x", simplifyPath("/a/b/c/;x"));
    193     assertEquals("/a/b/c/g;x", simplifyPath("/a/b/c/g;x"));
    194     assertEquals("/a/b/c/g;x?y#s", simplifyPath("/a/b/c/g;x?y#s"));
    195     assertEquals("/a/b/c", simplifyPath("/a/b/c/."));
    196     assertEquals("/a/b/c", simplifyPath("/a/b/c/./"));
    197     assertEquals("/a/b", simplifyPath("/a/b/c/.."));
    198     assertEquals("/a/b", simplifyPath("/a/b/c/../"));
    199     assertEquals("/a/b/g", simplifyPath("/a/b/c/../g"));
    200     assertEquals("/a", simplifyPath("/a/b/c/../.."));
    201     assertEquals("/a", simplifyPath("/a/b/c/../../"));
    202     assertEquals("/a/g", simplifyPath("/a/b/c/../../g"));
    203   }
    204 
    205   /** http://gbiv.com/protocols/uri/rfc/rfc2396.html#rfc.section.C.2 */
    206   public void testRfc2396Abnormal() {
    207     assertEquals("/a/b/c/g.", simplifyPath("/a/b/c/g."));
    208     assertEquals("/a/b/c/.g", simplifyPath("/a/b/c/.g"));
    209     assertEquals("/a/b/c/g..", simplifyPath("/a/b/c/g.."));
    210     assertEquals("/a/b/c/..g", simplifyPath("/a/b/c/..g"));
    211     assertEquals("/a/b/g", simplifyPath("/a/b/c/./../g"));
    212     assertEquals("/a/b/c/g", simplifyPath("/a/b/c/./g/."));
    213     assertEquals("/a/b/c/g/h", simplifyPath("/a/b/c/g/./h"));
    214     assertEquals("/a/b/c/h", simplifyPath("/a/b/c/g/../h"));
    215     assertEquals("/a/b/c/g;x=1/y", simplifyPath("/a/b/c/g;x=1/./y"));
    216     assertEquals("/a/b/c/y", simplifyPath("/a/b/c/g;x=1/../y"));
    217   }
    218 
    219   /** http://gbiv.com/protocols/uri/rfc/rfc3986.html#relative-normal */
    220   public void testRfc3986Normal() {
    221     assertEquals("/a/b/c/g", simplifyPath("/a/b/c/g"));
    222     assertEquals("/a/b/c/g", simplifyPath("/a/b/c/./g"));
    223     assertEquals("/a/b/c/g", simplifyPath("/a/b/c/g/"));
    224 
    225     assertEquals("/a/b/c/g?y", simplifyPath("/a/b/c/g?y"));
    226     assertEquals("/a/b/c/g#s", simplifyPath("/a/b/c/g#s"));
    227     assertEquals("/a/b/c/g?y#s", simplifyPath("/a/b/c/g?y#s"));
    228     assertEquals("/a/b/c/;x", simplifyPath("/a/b/c/;x"));
    229     assertEquals("/a/b/c/g;x", simplifyPath("/a/b/c/g;x"));
    230     assertEquals("/a/b/c/g;x?y#s", simplifyPath("/a/b/c/g;x?y#s"));
    231 
    232     assertEquals("/a/b/c", simplifyPath("/a/b/c/."));
    233     assertEquals("/a/b/c", simplifyPath("/a/b/c/./"));
    234     assertEquals("/a/b", simplifyPath("/a/b/c/.."));
    235     assertEquals("/a/b", simplifyPath("/a/b/c/../"));
    236     assertEquals("/a/b/g", simplifyPath("/a/b/c/../g"));
    237     assertEquals("/a", simplifyPath("/a/b/c/../.."));
    238     assertEquals("/a", simplifyPath("/a/b/c/../../"));
    239     assertEquals("/a/g", simplifyPath("/a/b/c/../../g"));
    240   }
    241 
    242   /** http://gbiv.com/protocols/uri/rfc/rfc3986.html#relative-abnormal */
    243   public void testRfc3986Abnormal() {
    244     assertEquals("/g", simplifyPath("/a/b/c/../../../g"));
    245     assertEquals("/g", simplifyPath("/a/b/c/../../../../g"));
    246 
    247     assertEquals("/a/b/c/g.", simplifyPath("/a/b/c/g."));
    248     assertEquals("/a/b/c/.g", simplifyPath("/a/b/c/.g"));
    249     assertEquals("/a/b/c/g..", simplifyPath("/a/b/c/g.."));
    250     assertEquals("/a/b/c/..g", simplifyPath("/a/b/c/..g"));
    251     assertEquals("/a/b/g", simplifyPath("/a/b/c/./../g"));
    252     assertEquals("/a/b/c/g", simplifyPath("/a/b/c/./g/."));
    253     assertEquals("/a/b/c/g/h", simplifyPath("/a/b/c/g/./h"));
    254     assertEquals("/a/b/c/h", simplifyPath("/a/b/c/g/../h"));
    255     assertEquals("/a/b/c/g;x=1/y", simplifyPath("/a/b/c/g;x=1/./y"));
    256     assertEquals("/a/b/c/y", simplifyPath("/a/b/c/g;x=1/../y"));
    257   }
    258 
    259   public void testExtensiveWithAbsolutePrefix() throws IOException {
    260     // Inputs are /b/c/<every possible 10-character string of characters "a./">
    261     // Expected outputs are from realpath -s.
    262     doExtensiveTest("testdata/simplifypathwithabsoluteprefixtests.txt");
    263   }
    264 
    265   public void testExtensiveNoPrefix() throws IOException {
    266     /*
    267      * Inputs are <every possible 10-character string of characters "a./">
    268      *
    269      * Expected outputs are generated by the code itself, but they've been
    270      * checked against the inputs under Bash in order to confirm that the two
    271      * forms are equivalent (though not necessarily minimal, though we hope this
    272      * to be the case). Thus, this test is more of a regression test.
    273      *
    274      * Rough instructions to regenerate the test outputs and verify correctness:
    275      * - Temporarily change this test:
    276      * --- Comment out assertEquals.
    277      * --- System.out.println(input + " " + simplifyPath(input));
    278      * --- fail(). (If the test were to pass, its output would be hidden.)
    279      * - Run the test.
    280      * - Pull the relevant lines of output from the test into a testcases file.
    281      * - Test the output:
    282      * --- cat testcases | while read L; do
    283      *       X=($L)
    284      *       A=$( cd /b/c && sudo mkdir -p ${X[0]} && cd ${X[0]} && pwd |
    285      *           sed -e 's#^//*#/#' )
    286      *       B=$( cd /b/c && cd ${X[1]} && pwd )
    287      *       cmp -s <(echo $A) <(echo $B) || echo "$X[0] -> $A vs. $B"
    288      *     done | tee testoutput
    289      * - Move that testcases file to the appropriate name under testdata.
    290      *
    291      * The last test will take hours, and if it passes, the output will be empty.
    292      */
    293     doExtensiveTest("testdata/simplifypathnoprefixtests.txt");
    294   }
    295 
    296   private void doExtensiveTest(String resourceName) throws IOException {
    297     Splitter splitter = Splitter.on(CharMatcher.WHITESPACE);
    298     URL url = getClass().getResource(resourceName);
    299     for (String line : Resources.readLines(url, UTF_8)) {
    300       Iterator<String> iterator = splitter.split(line).iterator();
    301       String input = iterator.next();
    302       String expectedOutput = iterator.next();
    303       assertFalse(iterator.hasNext());
    304       assertEquals(expectedOutput, simplifyPath(input));
    305     }
    306   }
    307 }
    308