1 /*
   2  * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.io.IOException;
  25 import java.nio.file.FileSystem;
  26 import java.nio.file.FileSystems;
  27 import java.nio.file.Files;
  28 import java.nio.file.InvalidPathException;
  29 import java.nio.file.Path;
  30 
  31 /**
  32  *
  33  * @test
  34  * @bug 8038500 8040059 8139956 8146754
  35  * @summary Tests path operations for zip provider.
  36  *
  37  * @run main PathOps
  38  * @run main/othervm/java.security.policy=test.policy PathOps
  39  * @modules jdk.zipfs
  40  */
  41 
  42 public class PathOps {
  43 
  44     static final java.io.PrintStream out = System.out;
  45     static FileSystem fs;
  46 
  47     private String input;
  48     private Path path;
  49     private Exception exc;
  50 
  51     private PathOps(String first, String... more) {
  52         out.println();
  53         input = first;
  54         try {
  55             path = fs.getPath(first, more);
  56             out.format("%s -> %s", first, path);
  57         } catch (Exception x) {
  58             exc = x;
  59             out.format("%s -> %s", first, x);
  60         }
  61         out.println();
  62     }
  63 
  64     Path path() {
  65         return path;
  66     }
  67 
  68     void fail() {
  69         throw new RuntimeException("PathOps failed");
  70     }
  71 
  72     void checkPath() {
  73         if (path == null) {
  74             throw new InternalError("path is null");
  75         }
  76     }
  77 
  78     void check(Object result, String expected) {
  79         out.format("\tExpected: %s\n", expected);
  80         out.format("\tActual: %s\n",  result);
  81         if (result == null) {
  82             if (expected == null) return;
  83         } else {
  84             // compare string representations
  85             if (expected != null && result.toString().equals(expected.toString()))
  86                 return;
  87         }
  88         fail();
  89     }
  90 
  91     void check(Object result, boolean expected) {
  92         check(result, Boolean.toString(expected));
  93     }
  94 
  95     PathOps root(String expected) {
  96         out.println("check root");
  97         checkPath();
  98         check(path.getRoot(), expected);
  99         return this;
 100     }
 101 
 102     PathOps parent(String expected) {
 103         out.println("check parent");
 104         checkPath();
 105         check(path.getParent(), expected);
 106         return this;
 107     }
 108 
 109     PathOps name(String expected) {
 110         out.println("check name");
 111         checkPath();
 112         check(path.getFileName(), expected);
 113         return this;
 114     }
 115 
 116     PathOps element(int index, String expected) {
 117         out.format("check element %d\n", index);
 118         checkPath();
 119         check(path.getName(index), expected);
 120         return this;
 121     }
 122 
 123     PathOps subpath(int startIndex, int endIndex, String expected) {
 124         out.format("test subpath(%d,%d)\n", startIndex, endIndex);
 125         checkPath();
 126         check(path.subpath(startIndex, endIndex), expected);
 127         return this;
 128     }
 129 
 130     PathOps starts(String prefix) {
 131         out.format("test startsWith with %s\n", prefix);
 132         checkPath();
 133         Path s = fs.getPath(prefix);
 134         check(path.startsWith(s), true);
 135         return this;
 136     }
 137 
 138     PathOps notStarts(String prefix) {
 139         out.format("test not startsWith with %s\n", prefix);
 140         checkPath();
 141         Path s = fs.getPath(prefix);
 142         check(path.startsWith(s), false);
 143         return this;
 144     }
 145 
 146     PathOps ends(String suffix) {
 147         out.format("test endsWith %s\n", suffix);
 148         checkPath();
 149         Path s = fs.getPath(suffix);
 150         check(path.endsWith(s), true);
 151         return this;
 152     }
 153 
 154     PathOps notEnds(String suffix) {
 155         out.format("test not endsWith %s\n", suffix);
 156         checkPath();
 157         Path s = fs.getPath(suffix);
 158         check(path.endsWith(s), false);
 159         return this;
 160     }
 161 
 162     PathOps absolute() {
 163         out.println("check path is absolute");
 164         checkPath();
 165         check(path.isAbsolute(), true);
 166         return this;
 167     }
 168 
 169     PathOps notAbsolute() {
 170         out.println("check path is not absolute");
 171         checkPath();
 172         check(path.isAbsolute(), false);
 173         return this;
 174     }
 175 
 176     PathOps resolve(String other, String expected) {
 177         out.format("test resolve %s\n", other);
 178         checkPath();
 179         check(path.resolve(other), expected);
 180         return this;
 181     }
 182 
 183     PathOps resolveSibling(String other, String expected) {
 184         out.format("test resolveSibling %s\n", other);
 185         checkPath();
 186         check(path.resolveSibling(other), expected);
 187         return this;
 188     }
 189 
 190     PathOps relativize(String other, String expected) {
 191         out.format("test relativize %s\n", other);
 192         checkPath();
 193         Path that = fs.getPath(other);
 194         check(path.relativize(that), expected);
 195         return this;
 196     }
 197 
 198     PathOps normalize(String expected) {
 199         out.println("check normalized path");
 200         checkPath();
 201         check(path.normalize(), expected);
 202         return this;
 203     }
 204 
 205     PathOps string(String expected) {
 206         out.println("check string representation");
 207         checkPath();
 208         check(path, expected);
 209         return this;
 210     }
 211 
 212     PathOps isSameFile(String target) {
 213         try {
 214             out.println("check two paths are same");
 215             checkPath();
 216             check(Files.isSameFile(path, test(target).path()), true);
 217         } catch (IOException ioe) {
 218             fail();
 219         }
 220         return this;
 221     }
 222 
 223     PathOps invalid() {
 224         if (!(exc instanceof InvalidPathException)) {
 225             out.println("InvalidPathException not thrown as expected");
 226             fail();
 227         }
 228         return this;
 229     }
 230 
 231     static PathOps test(String s) {
 232         return new PathOps(s);
 233     }
 234 
 235     static PathOps test(String first, String... more) {
 236         return new PathOps(first, more);
 237     }
 238 
 239     // -- PathOpss --
 240 
 241     static void header(String s) {
 242         out.println();
 243         out.println();
 244         out.println("-- " + s + " --");
 245     }
 246 
 247     static void doPathOpTests() {
 248         header("Path operations");
 249 
 250         // construction
 251         test("/")
 252             .string("/");
 253         test("/", "")
 254             .string("/");
 255         test("/", "foo")
 256             .string("/foo");
 257         test("/", "/foo")
 258             .string("/foo");
 259         test("/", "foo/")
 260             .string("/foo");
 261         test("foo", "bar", "gus")
 262             .string("foo/bar/gus");
 263         test("")
 264             .string("");
 265         test("", "/")
 266             .string("/");
 267         test("", "foo", "", "bar", "", "/gus")
 268             .string("foo/bar/gus");
 269 
 270         // all components
 271         test("/a/b/c")
 272             .root("/")
 273             .parent("/a/b")
 274             .name("c");
 275 
 276         // root component only
 277         test("/")
 278             .root("/")
 279             .parent(null)
 280             .name(null);
 281 
 282         // no root component
 283         test("a/b")
 284             .root(null)
 285             .parent("a")
 286             .name("b");
 287 
 288         // name component only
 289         test("foo")
 290             .root(null)
 291             .parent(null)
 292             .name("foo");
 293 
 294         // startsWith
 295         test("")
 296             .starts("")
 297             .notStarts("/");
 298         test("/")
 299             .starts("/")
 300             .notStarts("/foo");
 301         test("/foo")
 302             .starts("/")
 303             .starts("/foo")
 304             .notStarts("/f")
 305             .notStarts("");
 306         test("/foo/bar")
 307             .starts("/")
 308             .starts("/foo")
 309             .starts("/foo/")
 310             .starts("/foo/bar")
 311             .notStarts("/f")
 312             .notStarts("foo")
 313             .notStarts("foo/bar")
 314             .notStarts("");
 315         test("foo")
 316             .starts("foo")
 317             .notStarts("f");
 318         test("foo/bar")
 319             .starts("foo")
 320             .starts("foo/")
 321             .starts("foo/bar")
 322             .notStarts("f")
 323             .notStarts("/foo")
 324             .notStarts("/foo/bar");
 325 
 326         // endsWith
 327         test("")
 328             .ends("")
 329             .notEnds("/");
 330         test("/")
 331             .ends("/")
 332             .notEnds("foo")
 333             .notEnds("/foo");
 334         test("/foo")
 335             .ends("foo")
 336             .ends("/foo")
 337             .notEnds("/");
 338         test("/foo/bar")
 339             .ends("bar")
 340             .ends("foo/bar")
 341             .ends("foo/bar/")
 342             .ends("/foo/bar")
 343             .notEnds("/bar");
 344         test("/foo/bar/")
 345             .ends("bar")
 346             .ends("foo/bar")
 347             .ends("foo/bar/")
 348             .ends("/foo/bar")
 349             .notEnds("/bar");
 350         test("foo")
 351             .ends("foo");
 352         test("foo/bar")
 353             .ends("bar")
 354             .ends("bar/")
 355             .ends("foo/bar/")
 356             .ends("foo/bar");
 357 
 358         // elements
 359         test("a/b/c")
 360             .element(0,"a")
 361             .element(1,"b")
 362             .element(2,"c");
 363 
 364         // isAbsolute
 365         test("/")
 366             .absolute();
 367         test("/tmp")
 368             .absolute();
 369         test("tmp")
 370             .notAbsolute();
 371         test("")
 372             .notAbsolute();
 373 
 374         // resolve
 375         test("/tmp")
 376             .resolve("foo", "/tmp/foo")
 377             .resolve("/foo", "/foo")
 378             .resolve("", "/tmp");
 379         test("tmp")
 380             .resolve("foo", "tmp/foo")
 381             .resolve("/foo", "/foo")
 382             .resolve("", "tmp");
 383         test("")
 384             .resolve("", "")
 385             .resolve("foo", "foo")
 386             .resolve("/foo", "/foo");
 387 
 388         // resolveSibling
 389         test("foo")
 390             .resolveSibling("bar", "bar")
 391             .resolveSibling("/bar", "/bar")
 392             .resolveSibling("", "");
 393         test("foo/bar")
 394             .resolveSibling("gus", "foo/gus")
 395             .resolveSibling("/gus", "/gus")
 396             .resolveSibling("", "foo");
 397         test("/foo")
 398             .resolveSibling("gus", "/gus")
 399             .resolveSibling("/gus", "/gus")
 400             .resolveSibling("", "/");
 401         test("/foo/bar")
 402             .resolveSibling("gus", "/foo/gus")
 403             .resolveSibling("/gus", "/gus")
 404             .resolveSibling("", "/foo");
 405         test("")
 406             .resolveSibling("foo", "foo")
 407             .resolveSibling("/foo", "/foo")
 408             .resolve("", "");
 409 
 410         // relativize
 411         test("/a/b/c")
 412             .relativize("/a/b/c", "")
 413             .relativize("/a/b/c/d/e", "d/e")
 414             .relativize("/a/x", "../../x")
 415             .relativize("/x", "../../../x");
 416         test("a/b/c")
 417             .relativize("a/b/c/d", "d")
 418             .relativize("a/x", "../../x")
 419             .relativize("x", "../../../x")
 420             .relativize("", "../../..");
 421         test("")
 422             .relativize("a", "a")
 423             .relativize("a/b/c", "a/b/c")
 424             .relativize("", "");
 425         test("/")
 426             .relativize("/a", "a")
 427             .relativize("/a/c", "a/c");
 428         // 8146754
 429         test("/tmp/path")
 430             .relativize("/tmp/path/a.txt", "a.txt");
 431         test("/tmp/path/")
 432             .relativize("/tmp/path/a.txt", "a.txt");
 433 
 434         // normalize
 435         test("/")
 436             .normalize("/");
 437         test("foo")
 438             .normalize("foo");
 439         test("/foo")
 440             .normalize("/foo");
 441         test(".")
 442             .normalize("");
 443         test("..")
 444             .normalize("..");
 445         test("/..")
 446             .normalize("/");
 447         test("/../..")
 448             .normalize("/");
 449         test("foo/.")
 450             .normalize("foo");
 451         test("./foo")
 452             .normalize("foo");
 453         test("foo/..")
 454             .normalize("");
 455         test("../foo")
 456             .normalize("../foo");
 457         test("../../foo")
 458             .normalize("../../foo");
 459         test("foo/bar/..")
 460             .normalize("foo");
 461         test("foo/bar/gus/../..")
 462             .normalize("foo");
 463         test("/foo/bar/gus/../..")
 464             .normalize("/foo");
 465         test("/./.")
 466             .normalize("/");
 467         test("/.")
 468             .normalize("/");
 469         test("/./abc")
 470             .normalize("/abc");
 471         // invalid
 472         test("foo\u0000bar")
 473             .invalid();
 474         test("\u0000foo")
 475             .invalid();
 476         test("bar\u0000")
 477             .invalid();
 478         test("//foo\u0000bar")
 479             .invalid();
 480         test("//\u0000foo")
 481             .invalid();
 482         test("//bar\u0000")
 483             .invalid();
 484 
 485         // normalization
 486         test("//foo//bar")
 487             .string("/foo/bar")
 488             .root("/")
 489             .parent("/foo")
 490             .name("bar");
 491 
 492         // isSameFile
 493         test("/fileDoesNotExist")
 494             .isSameFile("/fileDoesNotExist");
 495 
 496         // 8139956
 497         out.println("check getNameCount");
 498         int nc = fs.getPath("/").relativize(fs.getPath("/")).getNameCount();
 499         if (nc != 1) {
 500             out.format("\tExpected: 1\n");
 501             out.format("\tActual: %d\n",  nc);
 502             throw new RuntimeException("getNameCount of empty path failed");
 503         }
 504      }
 505 
 506     static void npes() {
 507         header("NullPointerException");
 508 
 509         Path path = fs.getPath("foo");
 510 
 511         try {
 512             path.resolve((String)null);
 513             throw new RuntimeException("NullPointerException not thrown");
 514         } catch (NullPointerException npe) {
 515         }
 516 
 517         try {
 518             path.relativize(null);
 519             throw new RuntimeException("NullPointerException not thrown");
 520         } catch (NullPointerException npe) {
 521         }
 522 
 523         try {
 524             path.compareTo(null);
 525             throw new RuntimeException("NullPointerException not thrown");
 526         } catch (NullPointerException npe) {
 527         }
 528 
 529         try {
 530             path.startsWith((Path)null);
 531             throw new RuntimeException("NullPointerException not thrown");
 532         } catch (NullPointerException npe) {
 533         }
 534 
 535         try {
 536             path.endsWith((Path)null);
 537             throw new RuntimeException("NullPointerException not thrown");
 538         } catch (NullPointerException npe) {
 539         }
 540 
 541     }
 542 
 543     public static void main(String[] args) throws IOException {
 544         // create empty JAR file, test doesn't require any contents
 545         Path emptyJar = Utils.createJarFile("empty.jar");
 546 
 547         fs = FileSystems.newFileSystem(emptyJar, null);
 548         try {
 549         npes();
 550         doPathOpTests();
 551         } finally {
 552         fs.close();
 553     }
 554 }
 555 }