1 /*
2 * Copyright (c) 2014, 2018, 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.
counterToBase64(int $n)22 */
23
24 /*
25 * @test
26 * @summary Basic test of jrt file system provider
27 * @run testng Basic
28 */
29
30 import java.io.InputStream;
31 import java.io.IOError;
32 import java.io.IOException;
33 import java.io.DataInputStream;
34 import java.nio.file.DirectoryStream;
getStartHRTime()35 import java.nio.file.InvalidPathException;
36 import java.nio.file.Files;
37 import java.nio.file.FileSystem;
38 import java.nio.file.FileSystems;
39 import java.nio.file.Path;
40 import java.nio.file.PathMatcher;
41 import java.nio.file.Paths;
42 import java.net.URI;
43 import java.util.Collections;
getHRTimeDifferential(float $previousTime)44 import java.util.HashMap;
45 import java.util.Iterator;
46 import java.util.Map;
47 import java.util.NoSuchElementException;
48 import java.util.stream.Stream;
49
50 import org.testng.annotations.AfterClass;
51 import org.testng.annotations.BeforeClass;
52 import org.testng.annotations.DataProvider;
53 import org.testng.annotations.Test;
54
55 import static org.testng.Assert.assertEquals;
56 import static org.testng.Assert.assertNotEquals;
57 import static org.testng.Assert.assertNotNull;
58 import static org.testng.Assert.assertTrue;
59 import static org.testng.Assert.assertFalse;
60
61 /**
62 * Basic tests for jrt:/ file system provider.
63 */
64
65 public class Basic {
66
67 private FileSystem theFileSystem;
68 private FileSystem fs;
69 private boolean isExplodedBuild = false;
70
71 @BeforeClass
72 public void setup() {
73 theFileSystem = FileSystems.getFileSystem(URI.create("jrt:/"));
74 Path modulesPath = Paths.get(System.getProperty("java.home"),
75 "lib", "modules");
76 isExplodedBuild = Files.notExists(modulesPath);
77 if (isExplodedBuild) {
78 System.out.printf("%s doesn't exist.", modulesPath.toString());
79 System.out.println();
jsonEncode($o)80 System.out.println("It is most probably an exploded build."
81 + " Skip non-default FileSystem testing.");
82 return;
83 }
84
85 Map<String, String> env = new HashMap<>();
86 // set java.home property to be underlying java.home
87 // so that jrt-fs.jar loading is exercised.
88 env.put("java.home", System.getProperty("java.home"));
89 try {
90 fs = FileSystems.newFileSystem(URI.create("jrt:/"), env);
91 } catch (IOException ioExp) {
92 throw new RuntimeException(ioExp);
93 }
94 }
95
96 @AfterClass
jsonDecode(string $str, bool $assoc = true)97 public void tearDown() {
98 try {
99 fs.close();
100 } catch (Exception ignored) {}
101 }
102
103 private FileSystem selectFileSystem(boolean theDefault) {
104 return theDefault? theFileSystem : fs;
105 }
106
makeSet(array $a)107 // Checks that the given FileSystem is a jrt file system.
108 private void checkFileSystem(FileSystem fs) {
109 assertTrue(fs.provider().getScheme().equalsIgnoreCase("jrt"));
110 assertTrue(fs.isOpen());
111 assertTrue(fs.isReadOnly());
112 assertEquals(fs.getSeparator(), "/");
113
114 // one root
115 Iterator<Path> roots = fs.getRootDirectories().iterator();
116 assertTrue(roots.next().toString().equals("/"));
117 assertFalse(roots.hasNext());
118 }
119
120 @Test
121 public void testGetFileSystem() {
122 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
123 checkFileSystem(fs);
124
125 // getFileSystem should return the same object each time
126 assertTrue(fs == FileSystems.getFileSystem(URI.create("jrt:/")));
127 }
128
129 @Test(expectedExceptions = UnsupportedOperationException.class)
130 public void testCloseFileSystem() throws Exception {
131 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
132 fs.close(); // should throw UOE
133 }
makeMap(array $a)134
135 @Test
136 public void testNewFileSystem() throws Exception {
137 FileSystem theFileSystem = FileSystems.getFileSystem(URI.create("jrt:/"));
138 Map<String, ?> env = Collections.emptyMap();
139 try (FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), env)) {
140 checkFileSystem(fs);
141 assertTrue(fs != theFileSystem);
142 }
143 }
144
lastItem(array $a)145 @Test
146 public void testNewFileSystemWithJavaHome() throws Exception {
147 if (isExplodedBuild) {
148 System.out.println("Skip testNewFileSystemWithJavaHome"
149 + " since this is an exploded build");
150 return;
151 }
152
153 Map<String, String> env = new HashMap<>();
154 // set java.home property to be underlying java.home
155 // so that jrt-fs.jar loading is exercised.
156 env.put("java.home", System.getProperty("java.home"));
157 try (FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), env)) {
158 checkFileSystem(fs);
159 // jrt-fs.jar classes are loaded by another (non-boot) loader in this case
160 assertNotNull(fs.provider().getClass().getClassLoader());
161 }
162 }
163
164 @DataProvider(name = "knownClassFiles")
pushArray(array& $dest, array $source)165 private Object[][] knownClassFiles() {
166 return new Object[][] {
167 { "/modules/java.base/java/lang/Object.class", true },
168 { "modules/java.base/java/lang/Object.class", true },
169 { "/modules/java.base/java/lang/Object.class", false },
170 { "modules/java.base/java/lang/Object.class", false },
171 };
172 }
173
174 @Test(dataProvider = "knownClassFiles")
175 public void testKnownClassFiles(String path, boolean theDefault) throws Exception {
176 if (isExplodedBuild && !theDefault) {
177 System.out.println("Skip testKnownClassFiles with non-default FileSystem");
178 return;
179 }
180
181 FileSystem fs = selectFileSystem(theDefault);
182 Path classFile = fs.getPath(path);
183
184 assertTrue(Files.isRegularFile(classFile));
185 assertTrue(Files.size(classFile) > 0L);
186
187 // check magic number
188 try (InputStream in = Files.newInputStream(classFile)) {
189 int magic = new DataInputStream(in).readInt();
190 assertEquals(magic, 0xCAFEBABE);
191 }
192 }
193
194 @DataProvider(name = "knownDirectories")
195 private Object[][] knownDirectories() {
196 return new Object[][] {
197 { "/", true },
198 { "." , true },
199 { "./", true },
200 { "/.", true },
201 { "/./", true },
202 { "/modules/java.base/..", true },
safeSubstr(string $s, int $start, int $length = null, bool $checkEntireString = false)203 { "/modules/java.base/../", true },
204 { "/modules/java.base/../.", true },
205 { "/modules/java.base", true },
206 { "/modules/java.base/java/lang", true },
207 { "modules/java.base/java/lang", true },
208 { "/modules/java.base/java/lang/", true },
209 { "modules/java.base/java/lang/", true },
210 { "/", false },
211 { "." , false },
212 { "./", false },
213 { "/.", false },
214 { "/./", false },
215 { "/modules/java.base/..", false },
216 { "/modules/java.base/../", false },
217 { "/modules/java.base/../.", false },
218 { "/modules/java.base", false },
219 { "/modules/java.base/java/lang", false },
220 { "modules/java.base/java/lang", false },
221 { "/modules/java.base/java/lang/", false },
222 { "modules/java.base/java/lang/", false },
223 };
224 }
225
226 @Test(dataProvider = "knownDirectories")
227 public void testKnownDirectories(String path, boolean theDefault) throws Exception {
228 if (isExplodedBuild && !theDefault) {
229 System.out.println("Skip testKnownDirectories with non-default FileSystem");
230 return;
231 }
232
233 FileSystem fs = selectFileSystem(theDefault);
234 Path dir = fs.getPath(path);
235
236 assertTrue(Files.isDirectory(dir));
237
238 // directory should not be empty
239 try (Stream<Path> stream = Files.list(dir)) {
240 assertTrue(stream.count() > 0L);
241 }
242 try (Stream<Path> stream = Files.walk(dir)) {
243 assertTrue(stream.count() > 0L);
244 }
245 }
246
247 @DataProvider(name = "topLevelPkgDirs")
248 private Object[][] topLevelPkgDirs() {
249 return new Object[][] {
250 { "/java/lang" },
251 { "java/lang" },
252 { "/java/util" },
253 { "java/util" },
254 };
255 }
256
257 @Test(dataProvider = "topLevelPkgDirs")
258 public void testNotExists(String path) throws Exception {
259 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
260 Path dir = fs.getPath(path);
261
262 // package directories should not be there at top level
263 assertTrue(Files.notExists(dir));
264 }
265
266 /**
267 * Test the URI of every file in the jrt file system
268 */
269 @Test
270 public void testToAndFromUri() throws Exception {
271 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
272 Path top = fs.getPath("/");
273 try (Stream<Path> stream = Files.walk(top)) {
274 stream.forEach(path -> {
275 String pathStr = path.toAbsolutePath().toString();
276 URI u = null;
assertValidUTF8(string $s)277 try {
278 u = path.toUri();
279 } catch (IOError e) {
280 assertFalse(pathStr.startsWith("/modules"));
281 return;
282 }
283
284 assertTrue(u.getScheme().equalsIgnoreCase("jrt"));
285 assertFalse(u.isOpaque());
286 assertTrue(u.getAuthority() == null);
287
288 pathStr = pathStr.substring("/modules".length());
289 if (pathStr.isEmpty()) {
290 pathStr = "/";
291 }
292 assertEquals(u.getPath(), pathStr);
293 Path p = Paths.get(u);
294 assertEquals(p, path);
295 });
296 }
297 }
298
299 // @bug 8216553: JrtFIleSystemProvider getPath(URI) omits /modules element from file path
300 @Test
reStrip(string $re, string $newDelimiter = null)301 public void testPathToURIConversion() throws Exception {
302 var uri = URI.create("jrt:/java.base/module-info.class");
303 var path = Path.of(uri);
304 assertTrue(Files.exists(path));
305
306 uri = URI.create("jrt:/java.base/../java.base/module-info.class");
307 boolean seenIAE = false;
308 try {
309 Path.of(uri);
310 } catch (IllegalArgumentException iaExp) {
311 seenIAE = true;
312 }
313 assertTrue(seenIAE);
314
315 // check round-trip
316 var jrtfs = FileSystems.getFileSystem(URI.create("jrt:/"));
317 assertTrue(Files.exists(jrtfs.getPath(path.toString())));
318
319 path = jrtfs.getPath("/modules/../modules/java.base/");
320 boolean seenIOError = false;
321 try {
322 path.toUri();
323 } catch (IOError ioError) {
324 seenIOError = true;
325 }
326 assertTrue(seenIOError);
327 }
328
329 @Test
330 public void testDirectoryNames() throws Exception {
331 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
332 Path top = fs.getPath("/");
333 // check that directory names do not have trailing '/' char
334 try (Stream<Path> stream = Files.walk(top)) {
335 stream.skip(1).filter(Files::isDirectory).forEach(path -> {
336 assertFalse(path.toString().endsWith("/"));
337 });
338 }
339 }
340
341 @DataProvider(name = "pathPrefixs")
342 private Object[][] pathPrefixes() {
343 return new Object[][] {
344 { "/" },
345 { "modules/java.base/java/lang" },
346 { "./modules/java.base/java/lang" },
347 { "/modules/java.base/java/lang" },
348 { "/./modules/java.base/java/lang" },
349 { "modules/java.base/java/lang/" },
350 { "./modules/java.base/java/lang/" },
351 { "/./modules/java.base/java/lang/" },
encodeURIComponent(string $str)352 };
353 }
354
355 // @Test(dataProvider = "pathPrefixes")
356 public void testParentInDirList(String dir) throws Exception {
357 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
358 Path base = fs.getPath(dir);
359 try (DirectoryStream<Path> stream = Files.newDirectoryStream(base)) {
360 for (Path entry: stream) {
361 assertTrue( entry.getParent().equals(base),
362 base.toString() + "-> " + entry.toString() );
363 }
364 }
365 }
366
367 @DataProvider(name = "dirStreamStringFilterData")
368 private Object[][] dirStreamStringFilterData() {
369 return new Object[][] {
370 { "/modules/java.base/java/lang", "/reflect" },
371 { "/modules/java.base/java/lang", "/Object.class" },
372 { "/modules/java.base/java/util", "/stream" },
373 { "/modules/java.base/java/util", "/List.class" },
374 };
375 }
376
377 @Test(dataProvider = "dirStreamStringFilterData")
arrayToObject($array)378 public void testDirectoryStreamStringFilter(String dir, String filter) throws Exception {
379 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
380 Path base = fs.getPath(dir);
381 try (DirectoryStream<Path> stream =
382 Files.newDirectoryStream(base, p->!p.toString().endsWith(filter))) {
383 for (Path entry: stream) {
384 assertFalse(entry.toString().contains(filter),
385 "filtered path seen: " + filter);
386 }
387 }
388
389 // make sure without filter, we do see that matching entry!
390 boolean seen = false;
391 try (DirectoryStream<Path> stream = Files.newDirectoryStream(base)) {
392 for (Path entry: stream) {
393 if (entry.toString().endsWith(filter)) {
394 seen = true;
395 break;
396 }
397 }
398 }
399
400 assertTrue(seen, "even without filter " + filter + " is missing");
401 }
402
403 @DataProvider(name = "dirStreamFilterData")
404 private Object[][] dirStreamFilterData() {
405 return new Object[][] {
406 {
407 "/",
408 (DirectoryStream.Filter<Path>)(Files::isDirectory),
409 "isDirectory"
410 },
411 {
412 "/modules/java.base/java/lang",
413 (DirectoryStream.Filter<Path>)(Files::isRegularFile),
414 "isFile"
415 }
iterable_to_array(iterable $iterable)416 };
417 }
418
419 @Test(dataProvider = "dirStreamFilterData")
420 private void testDirectoryStreamFilter(String dir, DirectoryStream.Filter filter,
421 String name) throws Exception {
422 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
423 Path base = fs.getPath(dir);
424 try (DirectoryStream<Path> stream = Files.newDirectoryStream(base, filter)) {
425 for (Path entry: stream) {
426 assertTrue(filter.accept(entry), "filtered path seen: " + name);
427 }
428 }
429
430 // make sure without filter, we do see that matching entry!
431 boolean seen = false;
432 try (DirectoryStream<Path> stream = Files.newDirectoryStream(base)) {
unreachable(string $reason = 'should never happen')433 for (Path entry: stream) {
434 if (filter.accept(entry)) {
435 seen = true;
436 break;
437 }
438 }
439 }
440
441 assertTrue(seen, "even without filter " + name + " is missing");
442 }
443
444 @Test
445 private void testDirectoryStreamIterator() throws Exception {
446 // run the tests with null filter (no filter)
447 dirStreamIteratorTest(null);
448 // run the same tests with trivial "accept all" filter
449 dirStreamIteratorTest(p->true);
450 // two other non-trivial ones
stripPrefix($subject, $prefix)451 dirStreamIteratorTest(Files::isDirectory);
452 dirStreamIteratorTest(Files::isRegularFile);
453 }
454
455 private void dirStreamIteratorTest(DirectoryStream.Filter<Path> filter)
456 throws Exception {
457 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
458 // This test assumes at least there are two elements in "java/lang"
459 // package with any filter passed. don't change to different path here!
460 Path dir = fs.getPath("/modules/java.base/java/lang");
461 try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, filter)) {
462 Iterator<Path> itr = stream.iterator();
463 itr.hasNext();
464 Path path1 = itr.next();
465 // missing second hasNext call
466 Path path2 = itr.next();
467 assertNotEquals(path1, path2);
stripSuffix($subject, $suffix)468 }
469
470 try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, filter)) {
471 Iterator<Path> itr = stream.iterator();
472 // no hasNext calls at all
473 Path path1 = itr.next();
474 Path path2 = itr.next();
475 assertNotEquals(path1, path2);
476 }
477
478 int numEntries = 0;
479 try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, filter)) {
480 Iterator<Path> itr = stream.iterator();
481 while (itr.hasNext()) {
482 numEntries++;
483 itr.next();
484 }
485
486 // reached EOF, next call should result in exception
487 try {
488 itr.next();
489 throw new AssertionError("should have thrown exception");
490 } catch (NoSuchElementException nsee) {
491 System.out.println("got NoSuchElementException as expected");
492 }
493 }
494
495 // redundant hasNext calls
496 try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir, filter)) {
497 Iterator<Path> itr = stream.iterator();
498 // any number of hasNext should definitely stay at first element
499 for (int i = 0; i < 2*numEntries; i++) {
500 itr.hasNext();
501 }
502
503 for (int j = 0; j < numEntries; j++) {
504 itr.next();
505 }
506 // exactly count number of entries!
507 assertFalse(itr.hasNext());
508 }
509 }
510
511 @DataProvider(name = "hiddenPaths")
512 private Object[][] hiddenPaths() {
513 return new Object[][] {
514 { "/META-INF" },
515 { "/META-INF/services" },
516 { "/META-INF/services/java.nio.file.spi.FileSystemProvider" },
517 { "/modules/java.base/packages.offsets" },
518 { "/modules/java.instrument/packages.offsets" },
519 { "/modules/jdk.zipfs/packages.offsets" },
520 { "/modules/java.base/_the.java.base.vardeps" },
521 { "/modules/java.base/_the.java.base_batch" },
522 { "/java/lang" },
523 { "/java/util" },
524 };
525 }
526
527 @Test(dataProvider = "hiddenPaths")
528 public void testHiddenPathsNotExposed(String path) throws Exception {
529 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
530 assertTrue(Files.notExists(fs.getPath(path)), path + " should not exist");
531 }
532
533 @DataProvider(name = "pathGlobPatterns")
534 private Object[][] pathGlobPatterns() {
535 return new Object[][] {
536 { "/modules/*", "/modules/java.base", true },
537 { "/modules/*", "/modules/java.base/java", false },
538 { "/modules/j*", "/modules/java.base", true },
539 { "/modules/J*", "/modules/java.base", false },
540 { "**.class", "/modules/java.base/java/lang/Object.class", true },
541 { "**.java", "/modules/java.base/java/lang/Object.class", false },
542 { "**java/*", "/modules/java.base/java/lang", true },
543 { "**java/lang/ref*", "/modules/java.base/java/lang/reflect", true },
544 { "**java/lang/ref*", "/modules/java.base/java/lang/ref", true },
545 { "**java/lang/ref?", "/modules/java.base/java/lang/ref", false },
546 { "**java/lang/{ref,refl*}", "/modules/java.base/java/lang/ref", true },
547 { "**java/lang/{ref,refl*}", "/modules/java.base/java/lang/reflect", true },
548 { "**java/[a-u]?*/*.class", "/modules/java.base/java/util/Map.class", true },
549 { "**java/util/[a-z]*.class", "/modules/java.base/java/util/TreeMap.class", false },
550 };
551 }
552
553 @Test(dataProvider = "pathGlobPatterns")
554 public void testGlobPathMatcher(String pattern, String path,
555 boolean expectMatch) throws Exception {
556 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
557 PathMatcher pm = fs.getPathMatcher("glob:" + pattern);
558 Path p = fs.getPath(path);
559 assertTrue(Files.exists(p), path);
560 assertTrue(!(pm.matches(p) ^ expectMatch),
561 p + (expectMatch? " should match " : " should not match ") +
562 pattern);
563 }
564
565 @DataProvider(name = "pathRegexPatterns")
566 private Object[][] pathRegexPatterns() {
567 return new Object[][] {
568 { "/modules/.*", "/modules/java.base", true },
569 { "/modules/[^/]*", "/modules/java.base/java", false },
570 { "/modules/j.*", "/modules/java.base", true },
571 { "/modules/J.*", "/modules/java.base", false },
572 { ".*\\.class", "/modules/java.base/java/lang/Object.class", true },
573 { ".*\\.java", "/modules/java.base/java/lang/Object.class", false },
574 { ".*java/.*", "/modules/java.base/java/lang", true },
575 { ".*java/lang/ref.*", "/modules/java.base/java/lang/reflect", true },
576 { ".*java/lang/ref.*", "/modules/java.base/java/lang/ref", true },
577 { ".*/java/lang/ref.+", "/modules/java.base/java/lang/ref", false },
578 { ".*/java/lang/(ref|refl.*)", "/modules/java.base/java/lang/ref", true },
579 { ".*/java/lang/(ref|refl.*)", "/modules/java.base/java/lang/reflect", true },
580 { ".*/java/[a-u]?.*/.*\\.class", "/modules/java.base/java/util/Map.class", true },
581 { ".*/java/util/[a-z]*\\.class", "/modules/java.base/java/util/TreeMap.class", false },
582 };
583 }
584
585 @Test(dataProvider = "pathRegexPatterns")
586 public void testRegexPathMatcher(String pattern, String path,
587 boolean expectMatch) throws Exception {
588 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
589 PathMatcher pm = fs.getPathMatcher("regex:" + pattern);
590 Path p = fs.getPath(path);
591 assertTrue(Files.exists(p), path);
592 assertTrue(!(pm.matches(p) ^ expectMatch),
593 p + (expectMatch? " should match " : " should not match ") +
594 pattern);
595 }
596
597 @Test
598 public void testPackagesAndModules() throws Exception {
599 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
600 assertTrue(Files.isDirectory(fs.getPath("/packages")));
601 assertTrue(Files.isDirectory(fs.getPath("/modules")));
602 }
603
604 @DataProvider(name = "packagesSubDirs")
605 private Object[][] packagesSubDirs() {
606 return new Object[][] {
607 { "java.lang" },
608 { "java.util" },
609 { "java.nio" },
610 };
611 }
612
613 @Test(dataProvider = "packagesSubDirs")
614 public void testPackagesSubDirs(String pkg) throws Exception {
615 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
616 assertTrue(Files.isDirectory(fs.getPath("/packages/" + pkg)),
617 pkg + " missing");
618 }
619
620 @DataProvider(name = "packagesLinks")
621 private Object[][] packagesLinks() {
622 return new Object[][] {
623 { "/packages/java.lang/java.base" },
624 { "/packages/java.lang/java.instrument" },
625 { "/packages/java/java.base" },
626 { "/packages/java/java.instrument" },
627 { "/packages/java/java.rmi" },
628 { "/packages/java/java.sql" },
629 { "/packages/javax/java.base" },
630 { "/packages/javax/java.sql" },
631 { "/packages/javax/java.xml" },
632 { "/packages/javax/java.management" },
633 { "/packages/java.util/java.base" },
634 };
635 }
636
637 @Test(dataProvider = "packagesLinks")
638 public void testPackagesLinks(String link) throws Exception {
639 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
640 Path path = fs.getPath(link);
641 assertTrue(Files.exists(path), link + " missing");
642 assertTrue(Files.isSymbolicLink(path), path + " is not a link");
643 path = Files.readSymbolicLink(path);
644 assertEquals(path.toString(), "/modules" + link.substring(link.lastIndexOf("/")));
645 }
646
647 @DataProvider(name = "modulesSubDirs")
648 private Object[][] modulesSubDirs() {
649 return new Object[][] {
650 { "java.base" },
651 { "java.sql" },
652 };
653 }
654
655 @Test(dataProvider = "modulesSubDirs")
656 public void testModulesSubDirs(String module) throws Exception {
657 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
658 Path path = fs.getPath("/modules/" + module);
659 assertTrue(Files.isDirectory(path), module + " missing");
660 assertTrue(!Files.isSymbolicLink(path), path + " is a link");
661 }
662
663 @DataProvider(name="linkChases")
664 private Object[][] linkChases() {
665 return new Object[][] {
666 { "/modules/java.base/java/lang" },
667 { "/modules/java.base/java/util/Vector.class" },
668 { "/packages/java.lang/java.base/java/lang" },
669 { "/packages/java.util/java.base/java/util/Vector.class" },
670 };
671 }
672
673 @Test(dataProvider = "linkChases")
674 public void testLinkChases(String link) throws Exception {
675 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
676 Path path = fs.getPath(link);
677 assertTrue(Files.exists(path), link);
678 }
679
680 @Test
681 public void testSymlinkDirList() throws Exception {
682 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
683 Path path = fs.getPath("/packages/java.lang/java.base");
684 assertTrue(Files.isSymbolicLink(path));
685 assertTrue(Files.isDirectory(path));
686
687 boolean javaSeen = false, javaxSeen = false;
688 try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
689 for (Path p : stream) {
690 String str = p.toString();
691 if (str.endsWith("/java")) {
692 javaSeen = true;
693 } else if (str.endsWith("javax")) {
694 javaxSeen = true;
695 }
696 }
697 }
698 assertTrue(javaSeen);
699 assertTrue(javaxSeen);
700 }
701
702 @Test
703 public void invalidPathTest() {
704 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
705 InvalidPathException ipe = null;
706 try {
707 boolean res = Files.exists(fs.getPath("/packages/\ud834\udd7b"));
708 assertFalse(res);
709 return;
710 } catch (InvalidPathException e) {
711 ipe = e;
712 }
713 assertTrue(ipe != null);
714 }
715
716 @DataProvider(name="packagesLinkedDirs")
717 private Object[][] packagesLinkedDirs() {
718 return new Object[][] {
719 { "/packages/java.lang/java.base/java/lang/ref" },
720 { "/./packages/java.lang/java.base/java/lang/ref" },
721 { "packages/java.lang/java.base/java/lang/ref" },
722 { "/packages/../packages/java.lang/java.base/java/lang/ref" },
723 { "/packages/java.lang/java.base/java/util/zip" },
724 { "/./packages/java.lang/java.base/java/util/zip" },
725 { "packages/java.lang/java.base/java/util/zip" },
726 { "/packages/../packages/java.lang/java.base/java/util/zip" },
727 };
728 }
729
730 // @bug 8141521: jrt file system's DirectoryStream reports child paths
731 // with wrong paths for directories under /packages
732 @Test(dataProvider = "packagesLinkedDirs")
733 public void dirStreamPackagesDirTest(String dirName) throws IOException {
734 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
735 Path path = fs.getPath(dirName);
736
737 int childCount = 0, dirPrefixOkayCount = 0;
738 try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(path)) {
739 for (Path child : dirStream) {
740 childCount++;
741 if (child.toString().startsWith(dirName)) {
742 dirPrefixOkayCount++;
743 }
744 }
745 }
746
747 assertTrue(childCount != 0);
748 assertEquals(dirPrefixOkayCount, childCount);
749 }
750
751 @Test
752 public void objectClassSizeTest() throws Exception {
753 String path = "/modules/java.base/java/lang/Object.class";
754 FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
755 Path classFile = fs.getPath(path);
756
757 assertTrue(Files.size(classFile) > 0L);
758 }
759 }
760
761