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