jdk/test/java/nio/file/Files/StreamTest.java
changeset 17696 23a863fbb6c3
child 17943 a8293d390273
equal deleted inserted replaced
17695:032254f2467b 17696:23a863fbb6c3
       
     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 
       
    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.Comparators;
       
    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.function.BiPredicate;
       
    53 import java.util.stream.CloseableStream;
       
    54 import java.util.stream.Collectors;
       
    55 import org.testng.annotations.AfterClass;
       
    56 import org.testng.annotations.BeforeClass;
       
    57 import org.testng.annotations.Test;
       
    58 import static org.testng.Assert.*;
       
    59 
       
    60 @Test(groups = "unit")
       
    61 public 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 triggerFile = testFolder.resolve(Paths.get("dir", "SecurityException"));
       
   480         Files.createFile(triggerFile);
       
   481         Path sampleFile = testFolder.resolve(Paths.get("dir", "sample"));
       
   482         Files.createFile(sampleFile);
       
   483         Path triggerDir = testFolder.resolve(Paths.get("dir2", "SecurityException"));
       
   484         Files.createDirectories(triggerDir);
       
   485         Files.createFile(triggerDir.resolve("fileInSE"));
       
   486         Path sample = testFolder.resolve(Paths.get("dir2", "file"));
       
   487         Files.createFile(sample);
       
   488         FaultyFileSystem.FaultyFSProvider fsp = FaultyFileSystem.FaultyFSProvider.getInstance();
       
   489         FaultyFileSystem fs = (FaultyFileSystem) fsp.newFileSystem(testFolder, null);
       
   490 
       
   491         try {
       
   492             fsp.setFaultyMode(false);
       
   493             Path fakeRoot = fs.getRoot();
       
   494             // validate setting
       
   495             try (CloseableStream<Path> s = Files.list(fakeRoot.resolve("dir"))) {
       
   496                 String[] result = s.map(path -> path.getFileName().toString())
       
   497                                    .toArray(String[]::new);
       
   498                 assertEqualsNoOrder(result, new String[] { "d1","f1", "lnDir2", "SecurityException", "sample" });
       
   499             }
       
   500 
       
   501             try (CloseableStream<Path> s = Files.walk(fakeRoot.resolve("dir2"))) {
       
   502                 String[] result = s.map(path -> path.getFileName().toString())
       
   503                                    .toArray(String[]::new);
       
   504                 assertEqualsNoOrder(result, new String[] { "dir2", "SecurityException", "fileInSE", "file" });
       
   505             }
       
   506 
       
   507             // execute test
       
   508             fsp.setFaultyMode(true);
       
   509             // ignore file cause SecurityException
       
   510             try (CloseableStream<Path> s = Files.walk(fakeRoot.resolve("dir"))) {
       
   511                 String[] result = s.map(path -> path.getFileName().toString())
       
   512                                    .toArray(String[]::new);
       
   513                 assertEqualsNoOrder(result, new String[] { "dir", "d1","f1", "lnDir2", "sample" });
       
   514             }
       
   515             // skip folder cause SecurityException
       
   516             try (CloseableStream<Path> s = Files.walk(fakeRoot.resolve("dir2"))) {
       
   517                 String[] result = s.map(path -> path.getFileName().toString())
       
   518                                    .toArray(String[]::new);
       
   519                 assertEqualsNoOrder(result, new String[] { "dir2", "file" });
       
   520             }
       
   521 
       
   522             // list instead of walk
       
   523             try (CloseableStream<Path> s = Files.list(fakeRoot.resolve("dir"))) {
       
   524                 String[] result = s.map(path -> path.getFileName().toString())
       
   525                                    .toArray(String[]::new);
       
   526                 assertEqualsNoOrder(result, new String[] { "d1","f1", "lnDir2", "sample" });
       
   527             }
       
   528             try (CloseableStream<Path> s = Files.list(fakeRoot.resolve("dir2"))) {
       
   529                 String[] result = s.map(path -> path.getFileName().toString())
       
   530                                    .toArray(String[]::new);
       
   531                 assertEqualsNoOrder(result, new String[] { "file" });
       
   532             }
       
   533 
       
   534             // root cause SecurityException should be reported
       
   535             try (CloseableStream<Path> s = Files.walk(
       
   536                 fakeRoot.resolve("dir2").resolve("SecurityException")))
       
   537             {
       
   538                 String[] result = s.map(path -> path.getFileName().toString())
       
   539                                    .toArray(String[]::new);
       
   540                 fail("should not reach here due to SecurityException");
       
   541             } catch (SecurityException se) {
       
   542                 assertTrue(se.getCause() instanceof FaultyFileSystem.FaultyException);
       
   543             }
       
   544 
       
   545             // Walk a file cause SecurityException, we should get SE
       
   546             try (CloseableStream<Path> s = Files.walk(
       
   547                 fakeRoot.resolve("dir").resolve("SecurityException")))
       
   548             {
       
   549                 String[] result = s.map(path -> path.getFileName().toString())
       
   550                                    .toArray(String[]::new);
       
   551                 fail("should not reach here due to SecurityException");
       
   552             } catch (SecurityException se) {
       
   553                 assertTrue(se.getCause() instanceof FaultyFileSystem.FaultyException);
       
   554             }
       
   555 
       
   556             // List a file cause SecurityException, we should get SE as cannot read attribute
       
   557             try (CloseableStream<Path> s = Files.list(
       
   558                 fakeRoot.resolve("dir2").resolve("SecurityException")))
       
   559             {
       
   560                 String[] result = s.map(path -> path.getFileName().toString())
       
   561                                    .toArray(String[]::new);
       
   562                 fail("should not reach here due to SecurityException");
       
   563             } catch (SecurityException se) {
       
   564                 assertTrue(se.getCause() instanceof FaultyFileSystem.FaultyException);
       
   565             }
       
   566 
       
   567             try (CloseableStream<Path> s = Files.list(
       
   568                 fakeRoot.resolve("dir").resolve("SecurityException")))
       
   569             {
       
   570                 String[] result = s.map(path -> path.getFileName().toString())
       
   571                                    .toArray(String[]::new);
       
   572                 fail("should not reach here due to SecurityException");
       
   573             } catch (SecurityException se) {
       
   574                 assertTrue(se.getCause() instanceof FaultyFileSystem.FaultyException);
       
   575             }
       
   576          } finally {
       
   577             // Cleanup
       
   578             if (fs != null) {
       
   579                 fs.close();
       
   580             }
       
   581             Files.delete(triggerFile);
       
   582             Files.delete(sampleFile);
       
   583             Files.delete(sample);
       
   584             TestUtil.removeAll(triggerDir);
       
   585         }
       
   586     }
       
   587 
       
   588     public void testConstructException() {
       
   589         try (CloseableStream<String> s = Files.lines(testFolder.resolve("notExist"), Charset.forName("UTF-8"))) {
       
   590             s.forEach(l -> fail("File is not even exist!"));
       
   591         } catch (IOException ioe) {
       
   592             ioe.printStackTrace(System.err);
       
   593             assertTrue(ioe instanceof NoSuchFileException);
       
   594         }
       
   595     }
       
   596 
       
   597     public void testClosedStream() throws IOException {
       
   598         try (CloseableStream<Path> s = Files.list(testFolder)) {
       
   599             s.close();
       
   600             Object[] actual = s.sorted(Comparators.naturalOrder()).toArray();
       
   601             assertTrue(actual.length <= level1.length);
       
   602         }
       
   603 
       
   604         try (CloseableStream<Path> s = Files.walk(testFolder)) {
       
   605             s.close();
       
   606             Object[] actual = s.sorted(Comparators.naturalOrder()).toArray();
       
   607             fail("Operate on closed stream should throw IllegalStateException");
       
   608         } catch (IllegalStateException ex) {
       
   609             // expected
       
   610         }
       
   611 
       
   612         try (CloseableStream<Path> s = Files.find(testFolder, Integer.MAX_VALUE,
       
   613                     (p, attr) -> true)) {
       
   614             s.close();
       
   615             Object[] actual = s.sorted(Comparators.naturalOrder()).toArray();
       
   616             fail("Operate on closed stream should throw IllegalStateException");
       
   617         } catch (IllegalStateException ex) {
       
   618             // expected
       
   619         }
       
   620     }
       
   621 }