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