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