1/*
2 * Copyright (c) 2014, 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
24import java.nio.file.FileSystem;
25import java.nio.file.FileSystems;
26import java.nio.file.Files;
27import java.nio.file.Path;
28import java.nio.file.InvalidPathException;
29import java.net.URI;
30import java.io.IOException;
31
32/**
33 * @test
34 * @summary Tests jrt path operations
35 */
36
37public class PathOps {
38
39    static final java.io.PrintStream out = System.out;
40    static FileSystem fs;
41
42    private String input;
43    private Path path;
44    private Exception exc;
45
46    private PathOps(String first, String... more) {
47        out.println();
48        input = first;
49        try {
50            path = fs.getPath(first, more);
51            out.format("%s -> %s", first, path);
52        } catch (Exception x) {
53            exc = x;
54            out.format("%s -> %s", first, x);
55        }
56        out.println();
57    }
58
59    Path path() {
60        return path;
61    }
62
63    void fail() {
64        throw new RuntimeException("PathOps failed");
65    }
66
67    void checkPath() {
68        if (path == null) {
69            throw new InternalError("path is null");
70        }
71    }
72
73    void check(Object result, String expected) {
74        out.format("\tExpected: %s\n", expected);
75        out.format("\tActual: %s\n",  result);
76        if (result == null) {
77            if (expected == null) return;
78        } else {
79            // compare string representations
80            if (expected != null && result.toString().equals(expected.toString()))
81                return;
82        }
83        fail();
84    }
85
86    void check(Object result, boolean expected) {
87        check(result, Boolean.toString(expected));
88    }
89
90    PathOps root(String expected) {
91        out.println("check root");
92        checkPath();
93        check(path.getRoot(), expected);
94        return this;
95    }
96
97    PathOps parent(String expected) {
98        out.println("check parent");
99        checkPath();
100        check(path.getParent(), expected);
101        return this;
102    }
103
104    PathOps name(String expected) {
105        out.println("check name");
106        checkPath();
107        check(path.getFileName(), expected);
108        return this;
109    }
110
111    PathOps element(int index, String expected) {
112        out.format("check element %d\n", index);
113        checkPath();
114        check(path.getName(index), expected);
115        return this;
116    }
117
118    PathOps subpath(int startIndex, int endIndex, String expected) {
119        out.format("test subpath(%d,%d)\n", startIndex, endIndex);
120        checkPath();
121        check(path.subpath(startIndex, endIndex), expected);
122        return this;
123    }
124
125    PathOps starts(String prefix) {
126        out.format("test startsWith with %s\n", prefix);
127        checkPath();
128        Path s = fs.getPath(prefix);
129        check(path.startsWith(s), true);
130        return this;
131    }
132
133    PathOps notStarts(String prefix) {
134        out.format("test not startsWith with %s\n", prefix);
135        checkPath();
136        Path s = fs.getPath(prefix);
137        check(path.startsWith(s), false);
138        return this;
139    }
140
141    PathOps ends(String suffix) {
142        out.format("test endsWith %s\n", suffix);
143        checkPath();
144        Path s = fs.getPath(suffix);
145        check(path.endsWith(s), true);
146        return this;
147    }
148
149    PathOps notEnds(String suffix) {
150        out.format("test not endsWith %s\n", suffix);
151        checkPath();
152        Path s = fs.getPath(suffix);
153        check(path.endsWith(s), false);
154        return this;
155    }
156
157    PathOps absolute() {
158        out.println("check path is absolute");
159        checkPath();
160        check(path.isAbsolute(), true);
161        return this;
162    }
163
164    PathOps notAbsolute() {
165        out.println("check path is not absolute");
166        checkPath();
167        check(path.isAbsolute(), false);
168        return this;
169    }
170
171    PathOps resolve(String other, String expected) {
172        out.format("test resolve %s\n", other);
173        checkPath();
174        check(path.resolve(other), expected);
175        return this;
176    }
177
178    PathOps resolveSibling(String other, String expected) {
179        out.format("test resolveSibling %s\n", other);
180        checkPath();
181        check(path.resolveSibling(other), expected);
182        return this;
183    }
184
185    PathOps relativize(String other, String expected) {
186        out.format("test relativize %s\n", other);
187        checkPath();
188        Path that = fs.getPath(other);
189        check(path.relativize(that), expected);
190        return this;
191    }
192
193    PathOps normalize(String expected) {
194        out.println("check normalized path");
195        checkPath();
196        check(path.normalize(), expected);
197        return this;
198    }
199
200    PathOps string(String expected) {
201        out.println("check string representation");
202        checkPath();
203        check(path, expected);
204        return this;
205    }
206
207    PathOps isSameFile(String target) {
208        try {
209            out.println("check two paths are same");
210            checkPath();
211            check(Files.isSameFile(path, test(target).path()), true);
212        } catch (IOException ioe) {
213            fail();
214        }
215        return this;
216    }
217
218    PathOps invalid() {
219        if (!(exc instanceof InvalidPathException)) {
220            out.println("InvalidPathException not thrown as expected");
221            fail();
222        }
223        return this;
224    }
225
226    static PathOps test(String s) {
227        return new PathOps(s);
228    }
229
230    static PathOps test(String first, String... more) {
231        return new PathOps(first, more);
232    }
233
234    // -- PathOpss --
235
236    static void header(String s) {
237        out.println();
238        out.println();
239        out.println("-- " + s + " --");
240    }
241
242    static void doPathOpTests() {
243        header("Path operations");
244
245        // construction
246        test("/")
247            .string("/");
248        test("/", "")
249            .string("/");
250        test("/", "foo")
251            .string("/foo");
252        test("/", "/foo")
253            .string("/foo");
254        test("/", "foo/")
255            .string("/foo");
256        test("foo", "bar", "gus")
257            .string("foo/bar/gus");
258        test("")
259            .string("");
260        test("", "/")
261            .string("/");
262        test("", "foo", "", "bar", "", "/gus")
263            .string("foo/bar/gus");
264
265        // all components
266        test("/a/b/c")
267            .root("/")
268            .parent("/a/b")
269            .name("c");
270
271        // root component only
272        test("/")
273            .root("/")
274            .parent(null)
275            .name(null);
276
277        // no root component
278        test("a/b")
279            .root(null)
280            .parent("a")
281            .name("b");
282
283        // name component only
284        test("foo")
285             .root(null)
286             .parent(null)
287             .name("foo");
288        test("")
289             .root(null)
290             .parent(null)
291             .name("");
292
293        // startsWith
294        test("")
295            .starts("")
296            .notStarts("/");
297        test("/")
298            .starts("/")
299            .notStarts("")
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("")
318            .notStarts("f");
319        test("foo/bar")
320            .starts("foo")
321            .starts("foo/")
322            .starts("foo/bar")
323            .notStarts("f")
324            .notStarts("/foo")
325            .notStarts("/foo/bar");
326
327        // endsWith
328        test("")
329            .ends("")
330            .notEnds("/");
331        test("/")
332            .ends("/")
333            .notEnds("")
334            .notEnds("foo")
335            .notEnds("/foo");
336        test("/foo")
337            .ends("foo")
338            .ends("/foo")
339            .notEnds("/")
340            .notEnds("fool");
341        test("/foo/bar")
342            .ends("bar")
343            .ends("foo/bar")
344            .ends("foo/bar/")
345            .ends("/foo/bar")
346            .notEnds("/bar");
347        test("/foo/bar/")
348            .ends("bar")
349            .ends("foo/bar")
350            .ends("foo/bar/")
351            .ends("/foo/bar")
352            .notEnds("/bar");
353        test("foo")
354            .ends("foo")
355            .notEnds("")
356            .notEnds("oo")
357            .notEnds("oola");
358        test("foo/bar")
359            .ends("bar")
360            .ends("bar/")
361            .ends("foo/bar/")
362            .ends("foo/bar")
363            .notEnds("r")
364            .notEnds("barmaid")
365            .notEnds("/bar")
366            .notEnds("ar")
367            .notEnds("barack")
368            .notEnds("/bar")
369            .notEnds("o/bar");
370        test("foo/bar/gus")
371            .ends("gus")
372            .ends("bar/gus")
373            .ends("foo/bar/gus")
374            .notEnds("g")
375            .notEnds("/gus")
376            .notEnds("r/gus")
377            .notEnds("barack/gus")
378            .notEnds("bar/gust");
379
380        // elements
381        test("a/b/c")
382            .element(0,"a")
383            .element(1,"b")
384            .element(2,"c");
385
386        // isAbsolute
387        test("/")
388            .absolute();
389        test("/tmp")
390            .absolute();
391        test("tmp")
392            .notAbsolute();
393        test("")
394            .notAbsolute();
395
396        // resolve
397        test("/tmp")
398            .resolve("foo", "/tmp/foo")
399            .resolve("/foo", "/foo")
400            .resolve("", "/tmp");
401        test("tmp")
402            .resolve("foo", "tmp/foo")
403            .resolve("/foo", "/foo")
404            .resolve("", "tmp");
405        test("")
406            .resolve("", "")
407            .resolve("foo", "foo")
408            .resolve("/foo", "/foo");
409
410        // resolveSibling
411        test("foo")
412            .resolveSibling("bar", "bar")
413            .resolveSibling("/bar", "/bar")
414            .resolveSibling("", "");
415        test("foo/bar")
416            .resolveSibling("gus", "foo/gus")
417            .resolveSibling("/gus", "/gus")
418            .resolveSibling("", "foo");
419        test("/foo")
420            .resolveSibling("gus", "/gus")
421            .resolveSibling("/gus", "/gus")
422            .resolveSibling("", "/");
423        test("/foo/bar")
424            .resolveSibling("gus", "/foo/gus")
425            .resolveSibling("/gus", "/gus")
426            .resolveSibling("", "/foo");
427        test("")
428            .resolveSibling("foo", "foo")
429            .resolveSibling("/foo", "/foo")
430            .resolve("", "");
431
432        // relativize
433        test("/a/b/c")
434            .relativize("/a/b/c", "")
435            .relativize("/a/b/c/d/e", "d/e")
436            .relativize("/a/x", "../../x")
437            .relativize("/x", "../../../x");
438        test("a/b/c")
439            .relativize("a/b/c/d", "d")
440            .relativize("a/x", "../../x")
441            .relativize("x", "../../../x")
442            .relativize("", "../../..");
443        test("")
444            .relativize("a", "a")
445            .relativize("a/b/c", "a/b/c")
446            .relativize("", "");
447
448        // normalize
449        test("/")
450            .normalize("/");
451        test("foo")
452            .normalize("foo");
453        test("/foo")
454            .normalize("/foo");
455        test(".")
456            .normalize("");
457        test("..")
458            .normalize("..");
459        test("/..")
460            .normalize("/");
461        test("/../..")
462            .normalize("/");
463        test("foo/.")
464            .normalize("foo");
465        test("./foo")
466            .normalize("foo");
467        test("foo/..")
468            .normalize("");
469        test("../foo")
470            .normalize("../foo");
471        test("../../foo")
472            .normalize("../../foo");
473        test("foo/bar/..")
474            .normalize("foo");
475        test("foo/bar/gus/../..")
476            .normalize("foo");
477        test("/foo/bar/gus/../..")
478            .normalize("/foo");
479        test("/./.")
480            .normalize("/");
481        test("/.")
482            .normalize("/");
483        test("/./abc")
484            .normalize("/abc");
485        // invalid
486        test("foo\u0000bar")
487            .invalid();
488        test("\u0000foo")
489            .invalid();
490        test("bar\u0000")
491            .invalid();
492        test("//foo\u0000bar")
493            .invalid();
494        test("//\u0000foo")
495            .invalid();
496        test("//bar\u0000")
497            .invalid();
498
499        // normalization
500        test("//foo//bar")
501            .string("/foo/bar")
502            .root("/")
503            .parent("/foo")
504            .name("bar");
505
506        // isSameFile
507        test("/fileDoesNotExist")
508            .isSameFile("/fileDoesNotExist");
509    }
510
511    static void npes() {
512        header("NullPointerException");
513
514        Path path = fs.getPath("foo");
515
516        try {
517            path.resolve((String)null);
518            throw new RuntimeException("NullPointerException not thrown");
519        } catch (NullPointerException npe) {
520        }
521
522        try {
523            path.relativize(null);
524            throw new RuntimeException("NullPointerException not thrown");
525        } catch (NullPointerException npe) {
526        }
527
528        try {
529            path.compareTo(null);
530            throw new RuntimeException("NullPointerException not thrown");
531        } catch (NullPointerException npe) {
532        }
533
534        try {
535            path.startsWith((Path)null);
536            throw new RuntimeException("NullPointerException not thrown");
537        } catch (NullPointerException npe) {
538        }
539
540        try {
541            path.endsWith((Path)null);
542            throw new RuntimeException("NullPointerException not thrown");
543        } catch (NullPointerException npe) {
544        }
545
546    }
547
548    public static void main(String[] args) throws Throwable {
549        fs = FileSystems.getFileSystem(URI.create("jrt:/"));
550        npes();
551        doPathOpTests();
552    }
553}
554