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