1 /*
2  * Copyright (c) 2013, 2015, 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 8006884 8019526 8132539
26  * @library ..
27  * @build PassThroughFileSystem FaultyFileSystem
28  * @run testng StreamTest
29  * @summary Unit test for java.nio.file.Files methods that return a Stream
30  */
31 
32 import java.io.IOException;
33 import java.io.UncheckedIOException;
34 import java.nio.charset.Charset;
35 import java.nio.charset.MalformedInputException;
36 import java.nio.file.DirectoryIteratorException;
37 import java.nio.file.DirectoryStream;
38 import java.nio.file.FileSystemLoopException;
39 import java.nio.file.FileVisitOption;
40 import java.nio.file.Files;
41 import java.nio.file.NoSuchFileException;
42 import java.nio.file.Path;
43 import java.nio.file.Paths;
44 import java.nio.file.attribute.BasicFileAttributes;
45 import java.util.Arrays;
46 import java.util.Collections;
47 import java.util.Iterator;
48 import java.util.List;
49 import java.util.Objects;
50 import java.util.Set;
51 import java.util.TreeSet;
52 import java.util.concurrent.Callable;
53 import java.util.function.BiPredicate;
54 import java.util.stream.Stream;
55 import java.util.stream.Collectors;
56 import org.testng.annotations.AfterClass;
57 import org.testng.annotations.BeforeClass;
58 import org.testng.annotations.Test;
59 import static org.testng.Assert.*;
60 
61 @Test(groups = "unit")
62 public class StreamTest {
63     /**
64      * Default test folder
65      * testFolder - empty
66      *            - file
67      *            - dir - d1
68      *                  - f1
69      *                  - lnDir2 (../dir2)
70      *            - dir2
71      *            - linkDir (./dir)
72      *            - linkFile(./file)
73      */
74     static Path testFolder;
75     static boolean supportsLinks;
76     static Path[] level1;
77     static Path[] all;
78     static Path[] all_folowLinks;
79 
80     @BeforeClass
setupTestFolder()81     void setupTestFolder() throws IOException {
82         testFolder = TestUtil.createTemporaryDirectory();
83         supportsLinks = TestUtil.supportsLinks(testFolder);
84         TreeSet<Path> set = new TreeSet<>();
85 
86         // Level 1
87         Path empty = testFolder.resolve("empty");
88         Path file = testFolder.resolve("file");
89         Path dir = testFolder.resolve("dir");
90         Path dir2 = testFolder.resolve("dir2");
91         Files.createDirectory(empty);
92         Files.createFile(file);
93         Files.createDirectory(dir);
94         Files.createDirectory(dir2);
95         set.add(empty);
96         set.add(file);
97         set.add(dir);
98         set.add(dir2);
99         if (supportsLinks) {
100             Path tmp = testFolder.resolve("linkDir");
101             Files.createSymbolicLink(tmp, dir);
102             set.add(tmp);
103             tmp = testFolder.resolve("linkFile");
104             Files.createSymbolicLink(tmp, file);
105             set.add(tmp);
106         }
107         level1 = set.toArray(new Path[0]);
108 
109         // Level 2
110         Path tmp = dir.resolve("d1");
111         Files.createDirectory(tmp);
112         set.add(tmp);
113         tmp = dir.resolve("f1");
114         Files.createFile(tmp);
115         set.add(tmp);
116         if (supportsLinks) {
117             tmp = dir.resolve("lnDir2");
118             Files.createSymbolicLink(tmp, dir2);
119             set.add(tmp);
120         }
121         // walk include starting folder
122         set.add(testFolder);
123         all = set.toArray(new Path[0]);
124 
125         // Follow links
126         if (supportsLinks) {
127             tmp = testFolder.resolve("linkDir");
128             set.add(tmp.resolve("d1"));
129             set.add(tmp.resolve("f1"));
130             tmp = tmp.resolve("lnDir2");
131             set.add(tmp);
132         }
133         all_folowLinks = set.toArray(new Path[0]);
134     }
135 
136     @AfterClass
cleanupTestFolder()137     void cleanupTestFolder() throws IOException {
138         TestUtil.removeAll(testFolder);
139     }
140 
testBasic()141     public void testBasic() {
142         try (Stream<Path> s = Files.list(testFolder)) {
143             Object[] actual = s.sorted().toArray();
144             assertEquals(actual, level1);
145         } catch (IOException ioe) {
146             fail("Unexpected IOException");
147         }
148 
149         try (Stream<Path> s = Files.list(testFolder.resolve("empty"))) {
150             int count = s.mapToInt(p -> 1).reduce(0, Integer::sum);
151             assertEquals(count, 0, "Expect empty stream.");
152         } catch (IOException ioe) {
153             fail("Unexpected IOException");
154         }
155     }
156 
testWalk()157     public void testWalk() {
158         try (Stream<Path> s = Files.walk(testFolder)) {
159             Object[] actual = s.sorted().toArray();
160             assertEquals(actual, all);
161         } catch (IOException ioe) {
162             fail("Unexpected IOException");
163         }
164     }
165 
testWalkOneLevel()166     public void testWalkOneLevel() {
167         try (Stream<Path> s = Files.walk(testFolder, 1)) {
168             Object[] actual = s.filter(path -> ! path.equals(testFolder))
169                                .sorted()
170                                .toArray();
171             assertEquals(actual, level1);
172         } catch (IOException ioe) {
173             fail("Unexpected IOException");
174         }
175     }
176 
testWalkFollowLink()177     public void testWalkFollowLink() {
178         // If link is not supported, the directory structure won't have link.
179         // We still want to test the behavior with FOLLOW_LINKS option.
180         try (Stream<Path> s = Files.walk(testFolder, FileVisitOption.FOLLOW_LINKS)) {
181             Object[] actual = s.sorted().toArray();
182             assertEquals(actual, all_folowLinks);
183         } catch (IOException ioe) {
184             fail("Unexpected IOException");
185         }
186     }
187 
validateFileSystemLoopException(Path start, Path... causes)188     private void validateFileSystemLoopException(Path start, Path... causes) {
189         try (Stream<Path> s = Files.walk(start, FileVisitOption.FOLLOW_LINKS)) {
190             try {
191                 int count = s.mapToInt(p -> 1).reduce(0, Integer::sum);
192                 fail("Should got FileSystemLoopException, but got " + count + "elements.");
193             } catch (UncheckedIOException uioe) {
194                 IOException ioe = uioe.getCause();
195                 if (ioe instanceof FileSystemLoopException) {
196                     FileSystemLoopException fsle = (FileSystemLoopException) ioe;
197                     boolean match = false;
198                     for (Path cause: causes) {
199                         if (fsle.getFile().equals(cause.toString())) {
200                             match = true;
201                             break;
202                         }
203                     }
204                     assertTrue(match);
205                 } else {
206                     fail("Unexpected UncheckedIOException cause " + ioe.toString());
207                 }
208             }
209         } catch(IOException ex) {
210             fail("Unexpected IOException " + ex);
211         }
212     }
213 
testWalkFollowLinkLoop()214     public void testWalkFollowLinkLoop() {
215         if (!supportsLinks) {
216             return;
217         }
218 
219         // Loops.
220         try {
221             Path dir = testFolder.resolve("dir");
222             Path linkdir = testFolder.resolve("linkDir");
223             Path d1 = dir.resolve("d1");
224             Path cause = d1.resolve("lnSelf");
225             Files.createSymbolicLink(cause, d1);
226 
227             // loop in descendant.
228             validateFileSystemLoopException(dir, cause);
229             // loop in self
230             validateFileSystemLoopException(d1, cause);
231             // start from other place via link
232             validateFileSystemLoopException(linkdir,
233                     linkdir.resolve(Paths.get("d1", "lnSelf")));
234             Files.delete(cause);
235 
236             // loop to parent.
237             cause = d1.resolve("lnParent");
238             Files.createSymbolicLink(cause, dir);
239 
240             // loop should be detected at test/dir/d1/lnParent/d1
241             validateFileSystemLoopException(d1, cause.resolve("d1"));
242             // loop should be detected at link
243             validateFileSystemLoopException(dir, cause);
244             // loop should be detected at test/linkdir/d1/lnParent
245             // which is test/dir we have visited via test/linkdir
246             validateFileSystemLoopException(linkdir,
247                     linkdir.resolve(Paths.get("d1", "lnParent")));
248             Files.delete(cause);
249 
250             // cross loop
251             Path dir2 = testFolder.resolve("dir2");
252             cause = dir2.resolve("lnDir");
253             Files.createSymbolicLink(cause, dir);
254             validateFileSystemLoopException(dir,
255                     dir.resolve(Paths.get("lnDir2", "lnDir")));
256             validateFileSystemLoopException(dir2,
257                     dir2.resolve(Paths.get("lnDir", "lnDir2")));
258             validateFileSystemLoopException(linkdir,
259                     linkdir.resolve(Paths.get("lnDir2", "lnDir")));
260         } catch(IOException ioe) {
261             fail("Unexpected IOException " + ioe);
262         }
263     }
264 
265     private static class PathBiPredicate implements BiPredicate<Path, BasicFileAttributes> {
266         private final BiPredicate<Path, BasicFileAttributes> pred;
267         private final Set<Path> visited = new TreeSet<Path>();
268 
PathBiPredicate(BiPredicate<Path, BasicFileAttributes> pred)269         PathBiPredicate(BiPredicate<Path, BasicFileAttributes> pred) {
270             this.pred = Objects.requireNonNull(pred);
271         }
272 
test(Path path, BasicFileAttributes attrs)273         public boolean test(Path path, BasicFileAttributes attrs) {
274             visited.add(path);
275             return pred.test(path, attrs);
276         }
277 
visited()278         public Path[] visited() {
279             return visited.toArray(new Path[0]);
280         }
281     }
282 
testFind()283     public void testFind() throws IOException {
284         PathBiPredicate pred = new PathBiPredicate((path, attrs) -> true);
285 
286         try (Stream<Path> s = Files.find(testFolder, Integer.MAX_VALUE, pred)) {
287             Set<Path> result = s.collect(Collectors.toCollection(TreeSet::new));
288             assertEquals(pred.visited(), all);
289             assertEquals(result.toArray(new Path[0]), pred.visited());
290         }
291 
292         pred = new PathBiPredicate((path, attrs) -> attrs.isSymbolicLink());
293         try (Stream<Path> s = Files.find(testFolder, Integer.MAX_VALUE, pred)) {
294             s.forEach(path -> assertTrue(Files.isSymbolicLink(path)));
295             assertEquals(pred.visited(), all);
296         }
297 
298         pred = new PathBiPredicate((path, attrs) ->
299             path.getFileName().toString().startsWith("e"));
300         try (Stream<Path> s = Files.find(testFolder, Integer.MAX_VALUE, pred)) {
301             s.forEach(path -> assertEquals(path.getFileName().toString(), "empty"));
302             assertEquals(pred.visited(), all);
303         }
304 
305         pred = new PathBiPredicate((path, attrs) ->
306             path.getFileName().toString().startsWith("l") && attrs.isRegularFile());
307         try (Stream<Path> s = Files.find(testFolder, Integer.MAX_VALUE, pred)) {
308             s.forEach(path -> fail("Expect empty stream"));
309             assertEquals(pred.visited(), all);
310         }
311     }
312 
313     // Test borrowed from BytesAndLines
testLines()314     public void testLines() throws IOException {
315         final Charset US_ASCII = Charset.forName("US-ASCII");
316         Path tmpfile = Files.createTempFile("blah", "txt");
317 
318         try {
319             // zero lines
320             assertTrue(Files.size(tmpfile) == 0, "File should be empty");
321             try (Stream<String> s = Files.lines(tmpfile)) {
322                 checkLines(s, Collections.emptyList());
323             }
324             try (Stream<String> s = Files.lines(tmpfile, US_ASCII)) {
325                 checkLines(s, Collections.emptyList());
326             }
327 
328             // one line
329             List<String> oneLine = Arrays.asList("hi");
330             Files.write(tmpfile, oneLine, US_ASCII);
331             try (Stream<String> s = Files.lines(tmpfile)) {
332                 checkLines(s, oneLine);
333             }
334             try (Stream<String> s = Files.lines(tmpfile, US_ASCII)) {
335                 checkLines(s, oneLine);
336             }
337 
338             // two lines using platform's line separator
339             List<String> twoLines = Arrays.asList("hi", "there");
340             Files.write(tmpfile, twoLines, US_ASCII);
341             try (Stream<String> s = Files.lines(tmpfile)) {
342                 checkLines(s, twoLines);
343             }
344             try (Stream<String> s = Files.lines(tmpfile, US_ASCII)) {
345                 checkLines(s, twoLines);
346             }
347 
348             // MalformedInputException
349             byte[] bad = { (byte)0xff, (byte)0xff };
350             Files.write(tmpfile, bad);
351             try (Stream<String> s = Files.lines(tmpfile)) {
352                 checkMalformedInputException(s);
353             }
354             try (Stream<String> s = Files.lines(tmpfile, US_ASCII)) {
355                 checkMalformedInputException(s);
356             }
357 
358             // NullPointerException
359             checkNullPointerException(() -> Files.lines(null));
360             checkNullPointerException(() -> Files.lines(null, US_ASCII));
361             checkNullPointerException(() -> Files.lines(tmpfile, null));
362 
363         } finally {
364             Files.delete(tmpfile);
365         }
366     }
367 
checkLines(Stream<String> s, List<String> expected)368     private void checkLines(Stream<String> s, List<String> expected) {
369         List<String> lines = s.collect(Collectors.toList());
370         assertTrue(lines.size() == expected.size(), "Unexpected number of lines");
371         assertTrue(lines.equals(expected), "Unexpected content");
372     }
373 
checkMalformedInputException(Stream<String> s)374     private void checkMalformedInputException(Stream<String> s) {
375         try {
376             List<String> lines = s.collect(Collectors.toList());
377             fail("UncheckedIOException expected");
378         } catch (UncheckedIOException ex) {
379             IOException cause = ex.getCause();
380             assertTrue(cause instanceof MalformedInputException,
381                 "MalformedInputException expected");
382         }
383     }
384 
checkNullPointerException(Callable<?> c)385     private void checkNullPointerException(Callable<?> c) {
386         try {
387             c.call();
388             fail("NullPointerException expected");
389         } catch (NullPointerException ignore) {
390         } catch (Exception e) {
391             fail(e + " not expected");
392         }
393     }
394 
testDirectoryIteratorException()395     public void testDirectoryIteratorException() throws IOException {
396         Path dir = testFolder.resolve("dir2");
397         Path trigger = dir.resolve("DirectoryIteratorException");
398         Files.createFile(trigger);
399         FaultyFileSystem.FaultyFSProvider fsp = FaultyFileSystem.FaultyFSProvider.getInstance();
400         FaultyFileSystem fs = (FaultyFileSystem) fsp.newFileSystem(dir, null);
401 
402         try {
403             fsp.setFaultyMode(false);
404             Path fakeRoot = fs.getRoot();
405             try {
406                 try (Stream<Path> s = Files.list(fakeRoot)) {
407                     s.forEach(path -> assertEquals(path.getFileName().toString(), "DirectoryIteratorException"));
408                 }
409             } catch (UncheckedIOException uioe) {
410                 fail("Unexpected exception.");
411             }
412 
413             fsp.setFaultyMode(true);
414             try {
415                 try (DirectoryStream<Path> ds = Files.newDirectoryStream(fakeRoot)) {
416                     Iterator<Path> itor = ds.iterator();
417                     while (itor.hasNext()) {
418                         itor.next();
419                     }
420                 }
421                 fail("Shoule throw DirectoryIteratorException");
422             } catch (DirectoryIteratorException die) {
423             }
424 
425             try {
426                 try (Stream<Path> s = Files.list(fakeRoot)) {
427                     s.forEach(path -> fail("should not get here"));
428                 }
429             } catch (UncheckedIOException uioe) {
430                 assertTrue(uioe.getCause() instanceof FaultyFileSystem.FaultyException);
431             } catch (DirectoryIteratorException die) {
432                 fail("Should have been converted into UncheckedIOException.");
433             }
434         } finally {
435             // Cleanup
436             if (fs != null) {
437                 fs.close();
438             }
439             Files.delete(trigger);
440         }
441     }
442 
testUncheckedIOException()443     public void testUncheckedIOException() throws IOException {
444         Path triggerFile = testFolder.resolve(Paths.get("dir2", "IOException"));
445         Files.createFile(triggerFile);
446         Path triggerDir = testFolder.resolve(Paths.get("empty", "IOException"));
447         Files.createDirectories(triggerDir);
448         Files.createFile(triggerDir.resolve("file"));
449         FaultyFileSystem.FaultyFSProvider fsp = FaultyFileSystem.FaultyFSProvider.getInstance();
450         FaultyFileSystem fs = (FaultyFileSystem) fsp.newFileSystem(testFolder, null);
451 
452         try {
453             fsp.setFaultyMode(false);
454             Path fakeRoot = fs.getRoot();
455             try (Stream<Path> s = Files.list(fakeRoot.resolve("dir2"))) {
456                 // only one file
457                 s.forEach(path -> assertEquals(path.getFileName().toString(), "IOException"));
458             }
459 
460             try (Stream<Path> s = Files.walk(fakeRoot.resolve("empty"))) {
461                 String[] result = s.map(path -> path.getFileName().toString())
462                                    .toArray(String[]::new);
463                 // ordered as depth-first
464                 assertEquals(result, new String[] { "empty", "IOException", "file"});
465             }
466 
467             fsp.setFaultyMode(true);
468             try (Stream<Path> s = Files.list(fakeRoot.resolve("dir2"))) {
469                 s.forEach(path -> fail("should have caused exception"));
470             } catch (UncheckedIOException uioe) {
471                 assertTrue(uioe.getCause() instanceof FaultyFileSystem.FaultyException);
472             }
473 
474             try (Stream<Path> s = Files.walk(fakeRoot.resolve("empty"))) {
475                 String[] result = s.map(path -> path.getFileName().toString())
476                                    .toArray(String[]::new);
477                 fail("should not reach here due to IOException");
478             } catch (UncheckedIOException uioe) {
479                 assertTrue(uioe.getCause() instanceof FaultyFileSystem.FaultyException);
480             }
481 
482             try (Stream<Path> s = Files.walk(
483                 fakeRoot.resolve("empty").resolve("IOException")))
484             {
485                 String[] result = s.map(path -> path.getFileName().toString())
486                                    .toArray(String[]::new);
487                 fail("should not reach here due to IOException");
488             } catch (IOException ioe) {
489                 assertTrue(ioe instanceof FaultyFileSystem.FaultyException);
490             } catch (UncheckedIOException ex) {
491                 fail("Top level should be repored as is");
492             }
493          } finally {
494             // Cleanup
495             if (fs != null) {
496                 fs.close();
497             }
498             Files.delete(triggerFile);
499             TestUtil.removeAll(triggerDir);
500         }
501     }
502 
testSecurityException()503     public void testSecurityException() throws IOException {
504         Path empty = testFolder.resolve("empty");
505         Path triggerFile = Files.createFile(empty.resolve("SecurityException"));
506         Path sampleFile = Files.createDirectories(empty.resolve("sample"));
507 
508         Path dir2 = testFolder.resolve("dir2");
509         Path triggerDir = Files.createDirectories(dir2.resolve("SecurityException"));
510         Files.createFile(triggerDir.resolve("fileInSE"));
511         Path sample = Files.createFile(dir2.resolve("file"));
512 
513         Path triggerLink = null;
514         Path linkTriggerDir = null;
515         Path linkTriggerFile = null;
516         if (supportsLinks) {
517             Path dir = testFolder.resolve("dir");
518             triggerLink = Files.createSymbolicLink(dir.resolve("SecurityException"), empty);
519             linkTriggerDir = Files.createSymbolicLink(dir.resolve("lnDirSE"), triggerDir);
520             linkTriggerFile = Files.createSymbolicLink(dir.resolve("lnFileSE"), triggerFile);
521         }
522 
523         FaultyFileSystem.FaultyFSProvider fsp = FaultyFileSystem.FaultyFSProvider.getInstance();
524         FaultyFileSystem fs = (FaultyFileSystem) fsp.newFileSystem(testFolder, null);
525 
526         try {
527             fsp.setFaultyMode(false);
528             Path fakeRoot = fs.getRoot();
529             // validate setting
530             try (Stream<Path> s = Files.list(fakeRoot.resolve("empty"))) {
531                 String[] result = s.map(path -> path.getFileName().toString())
532                                    .toArray(String[]::new);
533                 assertEqualsNoOrder(result, new String[] { "SecurityException", "sample" });
534             }
535 
536             try (Stream<Path> s = Files.walk(fakeRoot.resolve("dir2"))) {
537                 String[] result = s.map(path -> path.getFileName().toString())
538                                    .toArray(String[]::new);
539                 assertEqualsNoOrder(result, new String[] { "dir2", "SecurityException", "fileInSE", "file" });
540             }
541 
542             if (supportsLinks) {
543                 try (Stream<Path> s = Files.list(fakeRoot.resolve("dir"))) {
544                     String[] result = s.map(path -> path.getFileName().toString())
545                                        .toArray(String[]::new);
546                     assertEqualsNoOrder(result, new String[] { "d1", "f1", "lnDir2", "SecurityException", "lnDirSE", "lnFileSE" });
547                 }
548             }
549 
550             // execute test
551             fsp.setFaultyMode(true);
552             // ignore file cause SecurityException
553             try (Stream<Path> s = Files.walk(fakeRoot.resolve("empty"))) {
554                 String[] result = s.map(path -> path.getFileName().toString())
555                                    .toArray(String[]::new);
556                 assertEqualsNoOrder(result, new String[] { "empty", "sample" });
557             }
558             // skip folder cause SecurityException
559             try (Stream<Path> s = Files.walk(fakeRoot.resolve("dir2"))) {
560                 String[] result = s.map(path -> path.getFileName().toString())
561                                    .toArray(String[]::new);
562                 assertEqualsNoOrder(result, new String[] { "dir2", "file" });
563             }
564 
565             if (supportsLinks) {
566                 // not following links
567                 try (Stream<Path> s = Files.walk(fakeRoot.resolve("dir"))) {
568                     String[] result = s.map(path -> path.getFileName().toString())
569                                        .toArray(String[]::new);
570                     assertEqualsNoOrder(result, new String[] { "dir", "d1", "f1", "lnDir2", "lnDirSE", "lnFileSE" });
571                 }
572 
573                 // following links
574                 try (Stream<Path> s = Files.walk(fakeRoot.resolve("dir"), FileVisitOption.FOLLOW_LINKS)) {
575                     String[] result = s.map(path -> path.getFileName().toString())
576                                        .toArray(String[]::new);
577                     // ?? Should fileInSE show up?
578                     // With FaultyFS, it does as no exception thrown for link to "SecurityException" with read on "lnXxxSE"
579                     assertEqualsNoOrder(result, new String[] { "dir", "d1", "f1", "lnDir2", "file", "lnDirSE", "lnFileSE", "fileInSE" });
580                 }
581             }
582 
583             // list instead of walk
584             try (Stream<Path> s = Files.list(fakeRoot.resolve("empty"))) {
585                 String[] result = s.map(path -> path.getFileName().toString())
586                                    .toArray(String[]::new);
587                 assertEqualsNoOrder(result, new String[] { "sample" });
588             }
589             try (Stream<Path> s = Files.list(fakeRoot.resolve("dir2"))) {
590                 String[] result = s.map(path -> path.getFileName().toString())
591                                    .toArray(String[]::new);
592                 assertEqualsNoOrder(result, new String[] { "file" });
593             }
594 
595             // root cause SecurityException should be reported
596             try (Stream<Path> s = Files.walk(
597                 fakeRoot.resolve("dir2").resolve("SecurityException")))
598             {
599                 String[] result = s.map(path -> path.getFileName().toString())
600                                    .toArray(String[]::new);
601                 fail("should not reach here due to SecurityException");
602             } catch (SecurityException se) {
603                 assertTrue(se.getCause() instanceof FaultyFileSystem.FaultyException);
604             }
605 
606             // Walk a file cause SecurityException, we should get SE
607             try (Stream<Path> s = Files.walk(
608                 fakeRoot.resolve("dir").resolve("SecurityException")))
609             {
610                 String[] result = s.map(path -> path.getFileName().toString())
611                                    .toArray(String[]::new);
612                 fail("should not reach here due to SecurityException");
613             } catch (SecurityException se) {
614                 assertTrue(se.getCause() instanceof FaultyFileSystem.FaultyException);
615             }
616 
617             // List a file cause SecurityException, we should get SE as cannot read attribute
618             try (Stream<Path> s = Files.list(
619                 fakeRoot.resolve("dir2").resolve("SecurityException")))
620             {
621                 String[] result = s.map(path -> path.getFileName().toString())
622                                    .toArray(String[]::new);
623                 fail("should not reach here due to SecurityException");
624             } catch (SecurityException se) {
625                 assertTrue(se.getCause() instanceof FaultyFileSystem.FaultyException);
626             }
627 
628             try (Stream<Path> s = Files.list(
629                 fakeRoot.resolve("dir").resolve("SecurityException")))
630             {
631                 String[] result = s.map(path -> path.getFileName().toString())
632                                    .toArray(String[]::new);
633                 fail("should not reach here due to SecurityException");
634             } catch (SecurityException se) {
635                 assertTrue(se.getCause() instanceof FaultyFileSystem.FaultyException);
636             }
637          } finally {
638             // Cleanup
639             if (fs != null) {
640                 fs.close();
641             }
642             if (supportsLinks) {
643                 Files.delete(triggerLink);
644                 Files.delete(linkTriggerDir);
645                 Files.delete(linkTriggerFile);
646             }
647             Files.delete(triggerFile);
648             Files.delete(sampleFile);
649             Files.delete(sample);
650             TestUtil.removeAll(triggerDir);
651         }
652     }
653 
testConstructException()654     public void testConstructException() {
655         try (Stream<String> s = Files.lines(testFolder.resolve("notExist"), Charset.forName("UTF-8"))) {
656             s.forEach(l -> fail("File is not even exist!"));
657         } catch (IOException ioe) {
658             assertTrue(ioe instanceof NoSuchFileException);
659         }
660     }
661 
testClosedStream()662     public void testClosedStream() throws IOException {
663         try (Stream<Path> s = Files.list(testFolder)) {
664             s.close();
665             Object[] actual = s.sorted().toArray();
666             fail("Operate on closed stream should throw IllegalStateException");
667         } catch (IllegalStateException ex) {
668             // expected
669         }
670 
671         try (Stream<Path> s = Files.walk(testFolder)) {
672             s.close();
673             Object[] actual = s.sorted().toArray();
674             fail("Operate on closed stream should throw IllegalStateException");
675         } catch (IllegalStateException ex) {
676             // expected
677         }
678 
679         try (Stream<Path> s = Files.find(testFolder, Integer.MAX_VALUE,
680                     (p, attr) -> true)) {
681             s.close();
682             Object[] actual = s.sorted().toArray();
683             fail("Operate on closed stream should throw IllegalStateException");
684         } catch (IllegalStateException ex) {
685             // expected
686         }
687     }
688 
testProcFile()689     public void testProcFile() throws IOException {
690         if (System.getProperty("os.name").equals("Linux")) {
691             Path path = Paths.get("/proc/cpuinfo");
692             if (Files.exists(path)) {
693                 String NEW_LINE = System.getProperty("line.separator");
694                 String s =
695                     Files.lines(path).collect(Collectors.joining(NEW_LINE));
696                 if (s.length() == 0) {
697                     fail("Files.lines(\"" + path + "\") returns no data");
698                 }
699             }
700         }
701     }
702 }
703