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
24import java.io.IOException;
25import java.nio.file.FileSystem;
26import java.nio.file.FileSystems;
27import java.nio.file.Files;
28import java.nio.file.InvalidPathException;
29import java.nio.file.Path;
30
31/**
32 *
33 * @test
34 * @bug 8038500 8040059 8139956 8146754 8172921
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
42public 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 resolvePath(String other, String expected) {
184        out.format("test resolve %s\n", other);
185        checkPath();
186        check(path.resolve(fs.getPath(other)), expected);
187        return this;
188    }
189
190    PathOps resolveSibling(String other, String expected) {
191        out.format("test resolveSibling %s\n", other);
192        checkPath();
193        check(path.resolveSibling(other), expected);
194        return this;
195    }
196
197    PathOps relativize(String other, String expected) {
198        out.format("test relativize %s\n", other);
199        checkPath();
200        Path that = fs.getPath(other);
201        check(path.relativize(that), expected);
202        return this;
203    }
204
205    PathOps normalize(String expected) {
206        out.println("check normalized path");
207        checkPath();
208        check(path.normalize(), expected);
209        return this;
210    }
211
212    PathOps string(String expected) {
213        out.println("check string representation");
214        checkPath();
215        check(path, expected);
216        return this;
217    }
218
219    PathOps isSameFile(String target) {
220        try {
221            out.println("check two paths are same");
222            checkPath();
223            check(Files.isSameFile(path, test(target).path()), true);
224        } catch (IOException ioe) {
225            fail();
226        }
227        return this;
228    }
229
230    PathOps invalid() {
231        if (!(exc instanceof InvalidPathException)) {
232            out.println("InvalidPathException not thrown as expected");
233            fail();
234        }
235        return this;
236    }
237
238    static PathOps test(String s) {
239        return new PathOps(s);
240    }
241
242    static PathOps test(String first, String... more) {
243        return new PathOps(first, more);
244    }
245
246    // -- PathOpss --
247
248    static void header(String s) {
249        out.println();
250        out.println();
251        out.println("-- " + s + " --");
252    }
253
254    static void doPathOpTests() {
255        header("Path operations");
256
257        // construction
258        test("/")
259            .string("/");
260        test("/", "")
261            .string("/");
262        test("/", "foo")
263            .string("/foo");
264        test("/", "/foo")
265            .string("/foo");
266        test("/", "foo/")
267            .string("/foo");
268        test("foo", "bar", "gus")
269            .string("foo/bar/gus");
270        test("")
271            .string("");
272        test("", "/")
273            .string("/");
274        test("", "foo", "", "bar", "", "/gus")
275            .string("foo/bar/gus");
276
277        // all components
278        test("/a/b/c")
279            .root("/")
280            .parent("/a/b")
281            .name("c");
282
283        // root component only
284        test("/")
285            .root("/")
286            .parent(null)
287            .name(null);
288
289        // no root component
290        test("a/b")
291            .root(null)
292            .parent("a")
293            .name("b");
294
295        // name component only
296        test("foo")
297            .root(null)
298            .parent(null)
299            .name("foo");
300
301        // startsWith
302        test("")
303            .starts("")
304            .notStarts("/");
305        test("/")
306            .starts("/")
307            .notStarts("/foo");
308        test("/foo")
309            .starts("/")
310            .starts("/foo")
311            .notStarts("/f")
312            .notStarts("");
313        test("/foo/bar")
314            .starts("/")
315            .starts("/foo")
316            .starts("/foo/")
317            .starts("/foo/bar")
318            .notStarts("/f")
319            .notStarts("foo")
320            .notStarts("foo/bar")
321            .notStarts("");
322        test("foo")
323            .starts("foo")
324            .notStarts("f");
325        test("foo/bar")
326            .starts("foo")
327            .starts("foo/")
328            .starts("foo/bar")
329            .notStarts("f")
330            .notStarts("/foo")
331            .notStarts("/foo/bar");
332
333        // endsWith
334        test("")
335            .ends("")
336            .notEnds("/");
337        test("/")
338            .ends("/")
339            .notEnds("foo")
340            .notEnds("/foo");
341        test("/foo")
342            .ends("foo")
343            .ends("/foo")
344            .notEnds("/");
345        test("/foo/bar")
346            .ends("bar")
347            .ends("foo/bar")
348            .ends("foo/bar/")
349            .ends("/foo/bar")
350            .notEnds("/bar");
351        test("/foo/bar/")
352            .ends("bar")
353            .ends("foo/bar")
354            .ends("foo/bar/")
355            .ends("/foo/bar")
356            .notEnds("/bar");
357        test("foo")
358            .ends("foo");
359        test("foo/bar")
360            .ends("bar")
361            .ends("bar/")
362            .ends("foo/bar/")
363            .ends("foo/bar");
364
365        // elements
366        test("a/b/c")
367            .element(0,"a")
368            .element(1,"b")
369            .element(2,"c");
370
371        // isAbsolute
372        test("/")
373            .absolute();
374        test("/tmp")
375            .absolute();
376        test("tmp")
377            .notAbsolute();
378        test("")
379            .notAbsolute();
380
381        // resolve
382        test("/tmp")
383            .resolve("foo", "/tmp/foo")
384            .resolve("/foo", "/foo")
385            .resolve("", "/tmp");
386        test("tmp")
387            .resolve("foo", "tmp/foo")
388            .resolve("/foo", "/foo")
389            .resolve("", "tmp");
390        test("")
391            .resolve("", "")
392            .resolve("foo", "foo")
393            .resolve("/foo", "/foo");
394        test("/")
395            .resolve("", "/")
396            .resolve("foo", "/foo")
397            .resolve("/foo", "/foo")
398            .resolve("/foo/", "/foo");
399
400        // resolve(Path)
401        test("/tmp")
402            .resolvePath("foo", "/tmp/foo")
403            .resolvePath("/foo", "/foo")
404            .resolvePath("", "/tmp");
405        test("tmp")
406            .resolvePath("foo", "tmp/foo")
407            .resolvePath("/foo", "/foo")
408            .resolvePath("", "tmp");
409        test("")
410            .resolvePath("", "")
411            .resolvePath("foo", "foo")
412            .resolvePath("/foo", "/foo");
413        test("/")
414            .resolvePath("", "/")
415            .resolvePath("foo", "/foo")
416            .resolvePath("/foo", "/foo")
417            .resolvePath("/foo/", "/foo");
418
419        // resolveSibling
420        test("foo")
421            .resolveSibling("bar", "bar")
422            .resolveSibling("/bar", "/bar")
423            .resolveSibling("", "");
424        test("foo/bar")
425            .resolveSibling("gus", "foo/gus")
426            .resolveSibling("/gus", "/gus")
427            .resolveSibling("", "foo");
428        test("/foo")
429            .resolveSibling("gus", "/gus")
430            .resolveSibling("/gus", "/gus")
431            .resolveSibling("", "/");
432        test("/foo/bar")
433            .resolveSibling("gus", "/foo/gus")
434            .resolveSibling("/gus", "/gus")
435            .resolveSibling("", "/foo");
436        test("")
437            .resolveSibling("foo", "foo")
438            .resolveSibling("/foo", "/foo")
439            .resolve("", "");
440
441        // relativize
442        test("/a/b/c")
443            .relativize("/a/b/c", "")
444            .relativize("/a/b/c/d/e", "d/e")
445            .relativize("/a/x", "../../x")
446            .relativize("/x", "../../../x");
447        test("a/b/c")
448            .relativize("a/b/c/d", "d")
449            .relativize("a/x", "../../x")
450            .relativize("x", "../../../x")
451            .relativize("", "../../..");
452        test("")
453            .relativize("a", "a")
454            .relativize("a/b/c", "a/b/c")
455            .relativize("", "");
456        test("/")
457            .relativize("/a", "a")
458            .relativize("/a/c", "a/c");
459        // 8146754
460        test("/tmp/path")
461            .relativize("/tmp/path/a.txt", "a.txt");
462        test("/tmp/path/")
463            .relativize("/tmp/path/a.txt", "a.txt");
464
465        // normalize
466        test("/")
467            .normalize("/");
468        test("foo")
469            .normalize("foo");
470        test("/foo")
471            .normalize("/foo");
472        test(".")
473            .normalize("");
474        test("..")
475            .normalize("..");
476        test("/..")
477            .normalize("/");
478        test("/../..")
479            .normalize("/");
480        test("foo/.")
481            .normalize("foo");
482        test("./foo")
483            .normalize("foo");
484        test("foo/..")
485            .normalize("");
486        test("../foo")
487            .normalize("../foo");
488        test("../../foo")
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        test("/./.")
497            .normalize("/");
498        test("/.")
499            .normalize("/");
500        test("/./abc")
501            .normalize("/abc");
502        // invalid
503        test("foo\u0000bar")
504            .invalid();
505        test("\u0000foo")
506            .invalid();
507        test("bar\u0000")
508            .invalid();
509        test("//foo\u0000bar")
510            .invalid();
511        test("//\u0000foo")
512            .invalid();
513        test("//bar\u0000")
514            .invalid();
515
516        // normalization
517        test("//foo//bar")
518            .string("/foo/bar")
519            .root("/")
520            .parent("/foo")
521            .name("bar");
522
523        // isSameFile
524        test("/fileDoesNotExist")
525            .isSameFile("/fileDoesNotExist");
526
527        // 8139956
528        out.println("check getNameCount");
529        int nc = fs.getPath("/").relativize(fs.getPath("/")).getNameCount();
530        if (nc != 1) {
531            out.format("\tExpected: 1\n");
532            out.format("\tActual: %d\n",  nc);
533            throw new RuntimeException("getNameCount of empty path failed");
534        }
535     }
536
537    static void npes() {
538        header("NullPointerException");
539
540        Path path = fs.getPath("foo");
541
542        try {
543            path.resolve((String)null);
544            throw new RuntimeException("NullPointerException not thrown");
545        } catch (NullPointerException npe) {
546        }
547
548        try {
549            path.relativize(null);
550            throw new RuntimeException("NullPointerException not thrown");
551        } catch (NullPointerException npe) {
552        }
553
554        try {
555            path.compareTo(null);
556            throw new RuntimeException("NullPointerException not thrown");
557        } catch (NullPointerException npe) {
558        }
559
560        try {
561            path.startsWith((Path)null);
562            throw new RuntimeException("NullPointerException not thrown");
563        } catch (NullPointerException npe) {
564        }
565
566        try {
567            path.endsWith((Path)null);
568            throw new RuntimeException("NullPointerException not thrown");
569        } catch (NullPointerException npe) {
570        }
571
572    }
573
574    public static void main(String[] args) throws IOException {
575        // create empty JAR file, test doesn't require any contents
576        Path emptyJar = Utils.createJarFile("empty.jar");
577
578        fs = FileSystems.newFileSystem(emptyJar, null);
579        try {
580        npes();
581        doPathOpTests();
582        } finally {
583        fs.close();
584    }
585}
586}
587