1 /*
   2  * Copyright 2008-2009 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  20  * CA 95054 USA or visit www.sun.com if you need additional information or
  21  * have any questions.
  22  */
  23 
  24 /* @test
  25  * @bug 4313887 6838333
  26  * @summary Unit test for java.nio.file.Path path operations
  27  */
  28 
  29 import java.nio.file.*;
  30 
  31 public class PathOps {
  32 
  33     static final java.io.PrintStream out = System.out;
  34 
  35     private String input;
  36     private Path path;
  37     private Exception exc;
  38 
  39     private PathOps(String s) {
  40         out.println();
  41         input = s;
  42         try {
  43             path = FileSystems.getDefault().getPath(s);
  44             out.format("%s -> %s", s, path);
  45         } catch (Exception x) {
  46             exc = x;
  47             out.format("%s -> %s", s, x);
  48         }
  49         out.println();
  50     }
  51 
  52     Path path() {
  53         return path;
  54     }
  55 
  56     void fail() {
  57         throw new RuntimeException("PathOps failed");
  58     }
  59 
  60     void checkPath() {
  61         if (path == null) {
  62             throw new InternalError("path is null");
  63         }
  64     }
  65 
  66     void check(Object result, String expected) {
  67         out.format("\tExpected: %s\n", expected);
  68         out.format("\tActual: %s\n",  result);
  69         if (result == null) {
  70             if (expected == null) return;
  71         } else {
  72             // compare string representations
  73             if (expected != null && result.toString().equals(expected.toString()))
  74                 return;
  75         }
  76         fail();
  77     }
  78 
  79     void check(Object result, boolean expected) {
  80         check(result, Boolean.toString(expected));
  81     }
  82 
  83     PathOps root(String expected) {
  84         out.println("check root");
  85         checkPath();
  86         check(path.getRoot(), expected);
  87         return this;
  88     }
  89 
  90     PathOps parent(String expected) {
  91         out.println("check parent");
  92         checkPath();
  93         check(path.getParent(), expected);
  94         return this;
  95     }
  96 
  97     PathOps name(String expected) {
  98         out.println("check name");
  99         checkPath();
 100         check(path.getName(), expected);
 101         return this;
 102     }
 103 
 104     PathOps element(int index, String expected) {
 105         out.format("check element %d\n", index);
 106         checkPath();
 107         check(path.getName(index), expected);
 108         return this;
 109     }
 110 
 111     PathOps subpath(int startIndex, int endIndex, String expected) {
 112         out.format("test subpath(%d,%d)\n", startIndex, endIndex);
 113         checkPath();
 114         check(path.subpath(startIndex, endIndex), expected);
 115         return this;
 116     }
 117 
 118     PathOps starts(String prefix) {
 119         out.format("test startsWith with %s\n", prefix);
 120         checkPath();
 121         Path s = FileSystems.getDefault().getPath(prefix);
 122         check(path.startsWith(s), true);
 123         return this;
 124     }
 125 
 126     PathOps notStarts(String prefix) {
 127         out.format("test not startsWith with %s\n", prefix);
 128         checkPath();
 129         Path s = FileSystems.getDefault().getPath(prefix);
 130         check(path.startsWith(s), false);
 131         return this;
 132     }
 133 
 134     PathOps ends(String suffix) {
 135         out.format("test endsWith %s\n", suffix);
 136         checkPath();
 137         Path s = FileSystems.getDefault().getPath(suffix);
 138         check(path.endsWith(s), true);
 139         return this;
 140     }
 141 
 142     PathOps notEnds(String suffix) {
 143         out.format("test not endsWith %s\n", suffix);
 144         checkPath();
 145         Path s = FileSystems.getDefault().getPath(suffix);
 146         check(path.endsWith(s), false);
 147         return this;
 148     }
 149 
 150     PathOps absolute() {
 151         out.println("check path is absolute");
 152         checkPath();
 153         check(path.isAbsolute(), true);
 154         return this;
 155     }
 156 
 157     PathOps notAbsolute() {
 158         out.println("check path is not absolute");
 159         checkPath();
 160         check(path.isAbsolute(), false);
 161         return this;
 162     }
 163 
 164     PathOps resolve(String other, String expected) {
 165         out.format("test resolve %s\n", other);
 166         checkPath();
 167         check(path.resolve(other), expected);
 168         return this;
 169     }
 170 
 171     PathOps relativize(String other, String expected) {
 172         out.format("test relativize %s\n", other);
 173         checkPath();
 174         Path that = FileSystems.getDefault().getPath(other);
 175         check(path.relativize(that), expected);
 176         return this;
 177     }
 178 
 179     PathOps normalize(String expected) {
 180         out.println("check normalized path");
 181         checkPath();
 182         check(path.normalize(), expected);
 183         return this;
 184     }
 185 
 186     PathOps string(String expected) {
 187         out.println("check string representation");
 188         checkPath();
 189         check(path, expected);
 190         return this;
 191     }
 192 
 193     PathOps invalid() {
 194         if (!(exc instanceof InvalidPathException)) {
 195             out.println("InvalidPathException not thrown as expected");
 196             fail();
 197         }
 198         return this;
 199     }
 200 
 201     static PathOps test(String s) {
 202         return new PathOps(s);
 203     }
 204 
 205     // -- PathOpss --
 206 
 207     static void header(String s) {
 208         out.println();
 209         out.println();
 210         out.println("-- " + s + " --");
 211     }
 212 
 213     static void doWindowsTests() {
 214         header("Windows specific tests");
 215 
 216         // all components present
 217         test("C:\\a\\b\\c")
 218             .root("C:\\")
 219             .parent("C:\\a\\b")
 220             .name("c");
 221         test("C:a\\b\\c")
 222             .root("C:")
 223             .parent("C:a\\b")
 224             .name("c");
 225         test("\\\\server\\share\\a")
 226             .root("\\\\server\\share\\")
 227             .parent("\\\\server\\share\\")
 228             .name("a");
 229 
 230         // root component only
 231         test("C:\\")
 232             .root("C:\\")
 233             .parent(null)
 234             .name(null);
 235         test("C:")
 236             .root("C:")
 237             .parent(null)
 238             .name(null);
 239         test("\\\\server\\share\\")
 240             .root("\\\\server\\share\\")
 241             .parent(null)
 242             .name(null);
 243 
 244         // no root component
 245         test("a\\b")
 246             .root(null)
 247             .parent("a")
 248             .name("b");
 249 
 250         // name component only
 251         test("foo")
 252             .root(null)
 253             .parent(null)
 254             .name("foo");
 255 
 256         // startsWith
 257         test("C:\\")
 258             .starts("C:\\")
 259             .starts("c:\\")
 260             .notStarts("C")
 261             .notStarts("C:");
 262         test("C:")
 263             .starts("C:")
 264             .starts("c:")
 265             .notStarts("C");
 266         test("\\")
 267             .starts("\\");
 268         test("C:\\foo\\bar")
 269             .starts("C:\\")
 270             .starts("C:\\foo")
 271             .starts("C:\\FOO")
 272             .starts("C:\\foo\\bar")
 273             .starts("C:\\Foo\\Bar")
 274             .notStarts("C:")
 275             .notStarts("C")
 276             .notStarts("C:foo");
 277         test("\\foo\\bar")
 278             .starts("\\")
 279             .starts("\\foo")
 280             .starts("\\foO")
 281             .starts("\\foo\\bar")
 282             .starts("\\fOo\\BaR")
 283             .notStarts("foo")
 284             .notStarts("foo\\bar");
 285         test("foo\\bar")
 286             .starts("foo")
 287             .starts("foo\\bar")
 288             .notStarts("\\");
 289         test("\\\\server\\share")
 290             .starts("\\\\server\\share")
 291             .starts("\\\\server\\share\\")
 292             .notStarts("\\");
 293 
 294         // endsWith
 295         test("C:\\")
 296             .ends("C:\\")
 297             .ends("c:\\")
 298             .notEnds("\\");
 299         test("C:")
 300             .ends("C:")
 301             .ends("c:");
 302         test("\\")
 303             .ends("\\");
 304         test("C:\\foo\\bar")
 305             .ends("bar")
 306             .ends("BAR")
 307             .ends("foo\\bar")
 308             .ends("Foo\\Bar")
 309             .ends("C:\\foo\\bar")
 310             .ends("c:\\foO\\baR")
 311             .notEnds("r")
 312             .notEnds("\\foo\\bar");
 313         test("\\foo\\bar")
 314             .ends("bar")
 315             .ends("BaR")
 316             .ends("foo\\bar")
 317             .ends("foO\\baR")
 318             .ends("\\foo\\bar")
 319             .ends("\\Foo\\Bar")
 320             .notEnds("oo\\bar");
 321         test("foo\\bar")
 322             .ends("bar")
 323             .ends("BAR")
 324             .ends("foo\\bar")
 325             .ends("Foo\\Bar")
 326             .notEnds("ar");
 327         test("\\\\server\\share")
 328             .ends("\\\\server\\share")
 329             .ends("\\\\server\\share\\")
 330             .notEnds("shared")
 331             .notEnds("\\");
 332 
 333         // elements
 334         test("C:\\a\\b\\c")
 335             .element(0, "a")
 336             .element(1, "b")
 337             .element(2, "c");
 338         test("foo.bar\\gus.alice")
 339             .element(0, "foo.bar")
 340             .element(1, "gus.alice");
 341 
 342         // subpath
 343         test("C:\\foo")
 344             .subpath(0, 1, "foo");
 345         test("C:foo")
 346             .subpath(0, 1, "foo");
 347         test("foo")
 348             .subpath(0, 1, "foo");
 349         test("C:\\foo\\bar\\gus")
 350             .subpath(0, 1, "foo")
 351             .subpath(0, 2, "foo\\bar")
 352             .subpath(0, 3, "foo\\bar\\gus")
 353             .subpath(1, 2, "bar")
 354             .subpath(1, 3, "bar\\gus")
 355             .subpath(2, 3, "gus");
 356         test("\\\\server\\share\\foo")
 357             .subpath(0, 1, "foo");
 358 
 359         // isAbsolute
 360         test("foo").notAbsolute();
 361         test("C:").notAbsolute();
 362         test("C:\\").absolute();
 363         test("C:\\abc").absolute();
 364         test("\\\\server\\share\\").absolute();
 365 
 366         // resolve
 367         test("C:\\")
 368             .resolve("foo", "C:\\foo")
 369             .resolve("D:\\bar", "D:\\bar")
 370             .resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar")
 371             .resolve("C:foo", "C:\\foo")
 372             .resolve("D:foo", "D:foo");
 373         test("\\")
 374             .resolve("foo", "\\foo")
 375             .resolve("D:bar", "D:bar")
 376             .resolve("C:\\bar", "C:\\bar")
 377             .resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar")
 378             .resolve("\\foo", "\\foo");
 379         test("\\foo")
 380             .resolve("bar", "\\foo\\bar")
 381             .resolve("D:bar", "D:bar")
 382             .resolve("C:\\bar", "C:\\bar")
 383             .resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar")
 384             .resolve("\\bar", "\\bar");
 385         test("foo")
 386             .resolve("bar", "foo\\bar")
 387             .resolve("D:\\bar", "D:\\bar")
 388             .resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar")
 389             .resolve("C:bar", "C:bar")
 390             .resolve("D:foo", "D:foo");
 391         test("C:")
 392             .resolve("foo", "C:foo");
 393         test("\\\\server\\share\\foo")
 394             .resolve("bar", "\\\\server\\share\\foo\\bar")
 395             .resolve("\\bar", "\\\\server\\share\\bar")
 396             .resolve("D:\\bar", "D:\\bar")
 397             .resolve("\\\\other\\share\\bar", "\\\\other\\share\\bar")
 398             .resolve("D:bar", "D:bar");
 399 
 400         // relativize
 401         test("foo\\bar")
 402             .relativize("foo\\bar", null)
 403             .relativize("foo", "..");
 404         test("C:\\a\\b\\c")
 405             .relativize("C:\\a", "..\\..");
 406         test("\\\\server\\share\\foo")
 407             .relativize("\\\\server\\share\\bar", "..\\bar");
 408 
 409         // normalize
 410         test("C:\\")
 411             .normalize("C:\\");
 412         test("C:\\.")
 413             .normalize("C:\\");
 414         test("C:\\..")
 415             .normalize("C:\\");
 416         test("\\\\server\\share")
 417             .normalize("\\\\server\\share\\");
 418         test("\\\\server\\share\\.")
 419             .normalize("\\\\server\\share\\");
 420         test("\\\\server\\share\\..")
 421             .normalize("\\\\server\\share\\");
 422         test("C:")
 423             .normalize("C:");
 424         test("C:.")
 425             .normalize("C:");
 426         test("C:..")
 427             .normalize("C:..");
 428         test("\\")
 429             .normalize("\\");
 430         test("\\.")
 431             .normalize("\\");
 432         test("\\..")
 433             .normalize("\\");
 434         test("foo")
 435             .normalize("foo");
 436         test("foo\\.")
 437             .normalize("foo");
 438         test("foo\\..")
 439             .normalize(null);
 440         test("C:\\foo")
 441             .normalize("C:\\foo");
 442         test("C:\\foo\\.")
 443             .normalize("C:\\foo");
 444         test("C:\\.\\foo")
 445             .normalize("C:\\foo");
 446         test("C:\\foo\\..")
 447             .normalize("C:\\");
 448         test("C:\\..\\foo")
 449             .normalize("C:\\foo");
 450         test("\\\\server\\share\\foo")
 451             .normalize("\\\\server\\share\\foo");
 452         test("\\\\server\\share\\foo\\.")
 453             .normalize("\\\\server\\share\\foo");
 454         test("\\\\server\\share\\.\\foo")
 455             .normalize("\\\\server\\share\\foo");
 456         test("\\\\server\\share\\foo\\..")
 457             .normalize("\\\\server\\share\\");
 458         test("\\\\server\\share\\..\\foo")
 459             .normalize("\\\\server\\share\\foo");
 460         test("C:foo")
 461             .normalize("C:foo");
 462         test("C:foo\\.")
 463             .normalize("C:foo");
 464         test("C:.\\foo")
 465             .normalize("C:foo");
 466         test("C:foo\\..")
 467             .normalize("C:");
 468         test("C:..\\foo")
 469             .normalize("C:..\\foo");
 470         test("\\foo")
 471             .normalize("\\foo");
 472         test("\\foo\\.")
 473             .normalize("\\foo");
 474         test("\\.\\foo")
 475             .normalize("\\foo");
 476         test("\\foo\\..")
 477             .normalize("\\");
 478         test("\\..\\foo")
 479             .normalize("\\foo");
 480         test(".")
 481             .normalize(null);
 482         test("..")
 483             .normalize("..");
 484         test("\\..\\..")
 485             .normalize("\\");
 486         test("..\\..\\foo")
 487             .normalize("..\\..\\foo");
 488         test("foo\\bar\\..")
 489             .normalize("foo");
 490         test("foo\\bar\\.\\..")
 491             .normalize("foo");
 492         test("foo\\bar\\gus\\..\\..")
 493             .normalize("foo");
 494         test(".\\foo\\.\\bar\\.\\gus\\..\\.\\..")
 495             .normalize("foo");
 496 
 497         // UNC corner cases
 498         test("\\\\server\\share\\")
 499             .root("\\\\server\\share\\")
 500             .parent(null)
 501             .name(null);
 502         test("\\\\server")
 503             .invalid();
 504         test("\\\\server\\")
 505             .invalid();
 506         test("\\\\server\\share")
 507             .root("\\\\server\\share\\")
 508             .parent(null)
 509             .name(null);
 510 
 511         // invalid
 512         test(":\\foo")
 513             .invalid();
 514         test("C::")
 515             .invalid();
 516         test("C:\\?")           // invalid character
 517             .invalid();
 518         test("C:\\*")           // invalid character
 519             .invalid();
 520         test("C:\\abc\u0001\\foo")
 521             .invalid();
 522         test("C:\\\u0019\\foo")
 523             .invalid();
 524         test("\\\\server\u0019\\share")
 525             .invalid();
 526         test("\\\\server\\share\u0019")
 527             .invalid();
 528         test("foo\u0000\bar")
 529             .invalid();
 530         test("C:\\foo ")                // trailing space
 531              .invalid();
 532         test("C:\\foo \\bar")
 533             .invalid();
 534         //test("C:\\foo.")              // trailing dot
 535             //.invalid();
 536         //test("C:\\foo...\\bar")
 537             //.invalid();
 538 
 539         // normalization at construction time (remove redundant and replace slashes)
 540         test("C:/a/b/c")
 541             .string("C:\\a\\b\\c")
 542             .root("C:\\")
 543             .parent("C:\\a\\b");
 544         test("C://a//b//c")
 545             .string("C:\\a\\b\\c")
 546             .root("C:\\")
 547             .parent("C:\\a\\b");
 548 
 549         // hashCode
 550         header("hashCode");
 551         int h1 = test("C:\\foo").path().hashCode();
 552         int h2 = test("c:\\FOO").path().hashCode();
 553         if (h1 != h2)
 554             throw new RuntimeException("PathOps failed");
 555     }
 556 
 557     static void doUnixTests() {
 558         header("Unix specific tests");
 559 
 560         // all components
 561         test("/a/b/c")
 562             .root("/")
 563             .parent("/a/b")
 564             .name("c");
 565 
 566         // root component only
 567         test("/")
 568             .root("/")
 569             .parent(null)
 570             .name(null);
 571 
 572         // no root component
 573         test("a/b")
 574             .root(null)
 575             .parent("a")
 576             .name("b");
 577 
 578         // name component only
 579         test("foo")
 580             .root(null)
 581             .parent(null)
 582             .name("foo");
 583 
 584         // startsWith
 585         test("/")
 586             .starts("/")
 587             .notStarts("/foo");
 588         test("/foo")
 589             .starts("/")
 590             .starts("/foo")
 591             .notStarts("/f");
 592         test("/foo/bar")
 593             .starts("/")
 594             .starts("/foo")
 595             .starts("/foo/bar")
 596             .notStarts("/f")
 597             .notStarts("foo")
 598             .notStarts("foo/bar");
 599         test("foo")
 600             .starts("foo")
 601             .notStarts("f");
 602         test("foo/bar")
 603             .starts("foo")
 604             .starts("foo/bar")
 605             .notStarts("f")
 606             .notStarts("/foo")
 607             .notStarts("/foo/bar");
 608 
 609         // endsWith
 610         test("/")
 611             .ends("/")
 612             .notEnds("foo")
 613             .notEnds("/foo");
 614         test("/foo")
 615             .ends("foo")
 616             .ends("/foo")
 617             .notEnds("/");
 618         test("/foo/bar")
 619             .ends("bar")
 620             .ends("foo/bar")
 621             .ends("/foo/bar")
 622             .notEnds("/bar");
 623         test("foo")
 624             .ends("foo");
 625         test("foo/bar")
 626             .ends("bar")
 627             .ends("foo/bar");
 628 
 629         // elements
 630         test("a/b/c")
 631             .element(0,"a")
 632             .element(1,"b")
 633             .element(2,"c");
 634 
 635         // isAbsolute
 636         test("/")
 637             .absolute();
 638         test("/tmp")
 639             .absolute();
 640         test("tmp")
 641             .notAbsolute();
 642 
 643         // resolve
 644         test("/tmp")
 645             .resolve("foo", "/tmp/foo")
 646             .resolve("/foo", "/foo");
 647         test("tmp")
 648             .resolve("foo", "tmp/foo")
 649             .resolve("/foo", "/foo");
 650 
 651         // relativize
 652         test("/a/b/c")
 653             .relativize("/a/b/c", null)
 654             .relativize("/a/b/c/d/e", "d/e")
 655             .relativize("/a/x", "../../x");
 656 
 657         // normalize
 658         test("/")
 659             .normalize("/");
 660         test("foo")
 661             .normalize("foo");
 662         test("/foo")
 663             .normalize("/foo");
 664         test(".")
 665             .normalize(null);
 666         test("..")
 667             .normalize("..");
 668         test("/..")
 669             .normalize("/");
 670         test("/../..")
 671             .normalize("/");
 672         test("foo/.")
 673             .normalize("foo");
 674         test("./foo")
 675             .normalize("foo");
 676         test("foo/..")
 677             .normalize(null);
 678         test("../foo")
 679             .normalize("../foo");
 680         test("../../foo")
 681             .normalize("../../foo");
 682         test("foo/bar/..")
 683             .normalize("foo");
 684         test("foo/bar/gus/../..")
 685             .normalize("foo");
 686         test("/foo/bar/gus/../..")
 687             .normalize("/foo");
 688 
 689         // invalid
 690         test("foo\u0000bar")
 691             .invalid();
 692         test("\u0000foo")
 693             .invalid();
 694         test("bar\u0000")
 695             .invalid();
 696         test("//foo\u0000bar")
 697             .invalid();
 698         test("//\u0000foo")
 699             .invalid();
 700         test("//bar\u0000")
 701             .invalid();
 702 
 703         // normalization
 704         test("//foo//bar")
 705             .string("/foo/bar")
 706             .root("/")
 707             .parent("/foo")
 708             .name("bar");
 709     }
 710 
 711     static void npes() {
 712         header("NullPointerException");
 713 
 714         Path path = FileSystems.getDefault().getPath("foo");
 715 
 716         try {
 717             path.resolve((String)null);
 718             throw new RuntimeException("NullPointerException not thrown");
 719         } catch (NullPointerException npe) {
 720         }
 721 
 722         try {
 723             path.relativize(null);
 724             throw new RuntimeException("NullPointerException not thrown");
 725         } catch (NullPointerException npe) {
 726         }
 727 
 728         try {
 729             path.compareTo(null);
 730             throw new RuntimeException("NullPointerException not thrown");
 731         } catch (NullPointerException npe) {
 732         }
 733 
 734         try {
 735             path.startsWith(null);
 736             throw new RuntimeException("NullPointerException not thrown");
 737         } catch (NullPointerException npe) {
 738         }
 739 
 740         try {
 741             path.endsWith(null);
 742             throw new RuntimeException("NullPointerException not thrown");
 743         } catch (NullPointerException npe) {
 744         }
 745 
 746     }
 747 
 748     public static void main(String[] args) {
 749         // all platforms
 750         npes();
 751 
 752         // operating system specific
 753         String osname = System.getProperty("os.name");
 754         if (osname.startsWith("Windows")) {
 755             doWindowsTests();
 756         }
 757         if (osname.equals("SunOS") || osname.equals("Linux")) {
 758             doUnixTests();
 759         }
 760 
 761     }
 762 }