1 /* 2 * Copyright (c) 2008, 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 4313887 6838333 6917021 7006126 6950237 8006645 26 * @summary Unit test for java.nio.file.Files copy and move methods 27 * @library .. 28 * @build CopyAndMove PassThroughFileSystem 29 * @run main/othervm CopyAndMove 30 * @key randomness 31 */ 32 33 import java.nio.ByteBuffer; 34 import java.nio.file.*; 35 import static java.nio.file.Files.*; 36 import static java.nio.file.StandardCopyOption.*; 37 import static java.nio.file.LinkOption.*; 38 import java.nio.file.attribute.*; 39 import java.io.*; 40 import java.util.*; 41 import java.util.concurrent.TimeUnit; 42 43 public class CopyAndMove { 44 static final Random rand = new Random(); heads()45 static boolean heads() { return rand.nextBoolean(); } 46 private static boolean testPosixAttributes = false; 47 main(String[] args)48 public static void main(String[] args) throws Exception { 49 Path dir1 = TestUtil.createTemporaryDirectory(); 50 try { 51 52 // Same directory 53 testPosixAttributes = getFileStore(dir1).supportsFileAttributeView("posix"); 54 testCopyFileToFile(dir1, dir1, TestUtil.supportsLinks(dir1)); 55 testMove(dir1, dir1, TestUtil.supportsLinks(dir1)); 56 57 // Different directories. Use test.dir if possible as it might be 58 // a different volume/file system and so improve test coverage. 59 String testDir = System.getProperty("test.dir", "."); 60 Path dir2 = TestUtil.createTemporaryDirectory(testDir); 61 try { 62 boolean testSymbolicLinks = 63 TestUtil.supportsLinks(dir1) && TestUtil.supportsLinks(dir2); 64 testPosixAttributes = getFileStore(dir1).supportsFileAttributeView("posix") && 65 getFileStore(dir2).supportsFileAttributeView("posix"); 66 testCopyFileToFile(dir1, dir2, testSymbolicLinks); 67 testMove(dir1, dir2, testSymbolicLinks); 68 } finally { 69 TestUtil.removeAll(dir2); 70 } 71 72 // Target is location associated with custom provider 73 Path dir3 = PassThroughFileSystem.create().getPath(dir1.toString()); 74 testPosixAttributes = getFileStore(dir1).supportsFileAttributeView("posix") && 75 getFileStore(dir3).supportsFileAttributeView("posix"); 76 testCopyFileToFile(dir1, dir3, false); 77 testMove(dir1, dir3, false); 78 79 // Test copy(InputStream,Path) and copy(Path,OutputStream) 80 testCopyInputStreamToFile(); 81 testCopyFileToOuputStream(); 82 83 } finally { 84 TestUtil.removeAll(dir1); 85 } 86 } 87 checkBasicAttributes(BasicFileAttributes attrs1, BasicFileAttributes attrs2)88 static void checkBasicAttributes(BasicFileAttributes attrs1, 89 BasicFileAttributes attrs2) 90 { 91 // check file type 92 assertTrue(attrs1.isRegularFile() == attrs2.isRegularFile()); 93 assertTrue(attrs1.isDirectory() == attrs2.isDirectory()); 94 assertTrue(attrs1.isSymbolicLink() == attrs2.isSymbolicLink()); 95 assertTrue(attrs1.isOther() == attrs2.isOther()); 96 97 // check last modified time if not a symbolic link 98 if (!attrs1.isSymbolicLink()) { 99 long time1 = attrs1.lastModifiedTime().to(TimeUnit.SECONDS); 100 long time2 = attrs2.lastModifiedTime().to(TimeUnit.SECONDS); 101 102 if (time1 != time2) { 103 System.err.format("File time for %s is %s\n", attrs1.fileKey(), attrs1.lastModifiedTime()); 104 System.err.format("File time for %s is %s\n", attrs2.fileKey(), attrs2.lastModifiedTime()); 105 assertTrue(false); 106 } 107 } 108 109 // check size 110 if (attrs1.isRegularFile()) 111 assertTrue(attrs1.size() == attrs2.size()); 112 } 113 checkPosixAttributes(PosixFileAttributes attrs1, PosixFileAttributes attrs2)114 static void checkPosixAttributes(PosixFileAttributes attrs1, 115 PosixFileAttributes attrs2) 116 { 117 assertTrue(attrs1.permissions().equals(attrs2.permissions())); 118 assertTrue(attrs1.owner().equals(attrs2.owner())); 119 assertTrue(attrs1.group().equals(attrs2.group())); 120 } 121 checkDosAttributes(DosFileAttributes attrs1, DosFileAttributes attrs2)122 static void checkDosAttributes(DosFileAttributes attrs1, 123 DosFileAttributes attrs2) 124 { 125 assertTrue(attrs1.isReadOnly() == attrs2.isReadOnly()); 126 assertTrue(attrs1.isHidden() == attrs2.isHidden()); 127 assertTrue(attrs1.isSystem() == attrs2.isSystem()); 128 } 129 checkUserDefinedFileAttributes(Map<String,ByteBuffer> attrs1, Map<String,ByteBuffer> attrs2)130 static void checkUserDefinedFileAttributes(Map<String,ByteBuffer> attrs1, 131 Map<String,ByteBuffer> attrs2) 132 { 133 assert attrs1.size() == attrs2.size(); 134 for (String name: attrs1.keySet()) { 135 ByteBuffer bb1 = attrs1.get(name); 136 ByteBuffer bb2 = attrs2.get(name); 137 assertTrue(bb2 != null); 138 assertTrue(bb1.equals(bb2)); 139 } 140 } 141 readUserDefinedFileAttributes(Path file)142 static Map<String,ByteBuffer> readUserDefinedFileAttributes(Path file) 143 throws IOException 144 { 145 UserDefinedFileAttributeView view = 146 getFileAttributeView(file, UserDefinedFileAttributeView.class); 147 Map<String,ByteBuffer> result = new HashMap<>(); 148 for (String name: view.list()) { 149 int size = view.size(name); 150 ByteBuffer bb = ByteBuffer.allocate(size); 151 int n = view.read(name, bb); 152 assertTrue(n == size); 153 bb.flip(); 154 result.put(name, bb); 155 } 156 return result; 157 } 158 159 // move source to target with verification moveAndVerify(Path source, Path target, CopyOption... options)160 static void moveAndVerify(Path source, Path target, CopyOption... options) 161 throws IOException 162 { 163 // read attributes before file is moved 164 BasicFileAttributes basicAttributes = null; 165 PosixFileAttributes posixAttributes = null; 166 DosFileAttributes dosAttributes = null; 167 Map<String,ByteBuffer> namedAttributes = null; 168 169 // get file attributes of source file 170 String os = System.getProperty("os.name"); 171 if (os.startsWith("Windows")) { 172 dosAttributes = readAttributes(source, DosFileAttributes.class, NOFOLLOW_LINKS); 173 basicAttributes = dosAttributes; 174 } else { 175 posixAttributes = readAttributes(source, PosixFileAttributes.class, NOFOLLOW_LINKS); 176 basicAttributes = posixAttributes; 177 } 178 if (basicAttributes == null) 179 basicAttributes = readAttributes(source, BasicFileAttributes.class, NOFOLLOW_LINKS); 180 181 // hash file contents if regular file 182 int hash = (basicAttributes.isRegularFile()) ? computeHash(source) : 0; 183 184 // record link target if symbolic link 185 Path linkTarget = null; 186 if (basicAttributes.isSymbolicLink()) 187 linkTarget = readSymbolicLink(source); 188 189 // read named attributes if available (and file is not a sym link) 190 if (!basicAttributes.isSymbolicLink() && 191 getFileStore(source).supportsFileAttributeView("xattr")) 192 { 193 namedAttributes = readUserDefinedFileAttributes(source); 194 } 195 196 // move file 197 Path result = move(source, target, options); 198 assertTrue(result == target); 199 200 // verify source does not exist 201 assertTrue(notExists(source)); 202 203 // verify file contents 204 if (basicAttributes.isRegularFile()) { 205 if (computeHash(target) != hash) 206 throw new RuntimeException("Failed to verify move of regular file"); 207 } 208 209 // verify link target 210 if (basicAttributes.isSymbolicLink()) { 211 if (!readSymbolicLink(target).equals(linkTarget)) 212 throw new RuntimeException("Failed to verify move of symbolic link"); 213 } 214 215 // verify basic attributes 216 checkBasicAttributes(basicAttributes, 217 readAttributes(target, BasicFileAttributes.class, NOFOLLOW_LINKS)); 218 219 // verify other attributes when same provider 220 if (source.getFileSystem().provider() == target.getFileSystem().provider()) { 221 222 // verify POSIX attributes 223 if (posixAttributes != null && 224 !basicAttributes.isSymbolicLink() && 225 testPosixAttributes) 226 { 227 checkPosixAttributes(posixAttributes, 228 readAttributes(target, PosixFileAttributes.class, NOFOLLOW_LINKS)); 229 } 230 231 // verify DOS attributes 232 if (dosAttributes != null && !basicAttributes.isSymbolicLink()) { 233 DosFileAttributes attrs = 234 readAttributes(target, DosFileAttributes.class, NOFOLLOW_LINKS); 235 checkDosAttributes(dosAttributes, attrs); 236 } 237 238 // verify named attributes 239 if (namedAttributes != null && 240 getFileStore(target).supportsFileAttributeView("xattr")) 241 { 242 checkUserDefinedFileAttributes(namedAttributes, 243 readUserDefinedFileAttributes(target)); 244 } 245 } 246 } 247 248 /** 249 * Tests all possible ways to invoke move 250 */ testMove(Path dir1, Path dir2, boolean supportsLinks)251 static void testMove(Path dir1, Path dir2, boolean supportsLinks) 252 throws IOException 253 { 254 Path source, target, entry; 255 256 boolean sameDevice = getFileStore(dir1).equals(getFileStore(dir2)); 257 258 // -- regular file -- 259 260 /** 261 * Test: move regular file, target does not exist 262 */ 263 source = createSourceFile(dir1); 264 target = getTargetFile(dir2); 265 moveAndVerify(source, target); 266 delete(target); 267 268 /** 269 * Test: move regular file, target exists 270 */ 271 source = createSourceFile(dir1); 272 target = getTargetFile(dir2); 273 createFile(target); 274 try { 275 moveAndVerify(source, target); 276 throw new RuntimeException("FileAlreadyExistsException expected"); 277 } catch (FileAlreadyExistsException x) { 278 } 279 delete(target); 280 createDirectory(target); 281 try { 282 moveAndVerify(source, target); 283 throw new RuntimeException("FileAlreadyExistsException expected"); 284 } catch (FileAlreadyExistsException x) { 285 } 286 delete(source); 287 delete(target); 288 289 /** 290 * Test: move regular file, target does not exist 291 */ 292 source = createSourceFile(dir1); 293 target = getTargetFile(dir2); 294 moveAndVerify(source, target, REPLACE_EXISTING); 295 delete(target); 296 297 /** 298 * Test: move regular file, target exists 299 */ 300 source = createSourceFile(dir1); 301 target = getTargetFile(dir2); 302 createFile(target); 303 moveAndVerify(source, target, REPLACE_EXISTING); 304 delete(target); 305 306 /** 307 * Test: move regular file, target exists and is empty directory 308 */ 309 source = createSourceFile(dir1); 310 target = getTargetFile(dir2); 311 createDirectory(target); 312 moveAndVerify(source, target, REPLACE_EXISTING); 313 delete(target); 314 315 /** 316 * Test: move regular file, target exists and is non-empty directory 317 */ 318 source = createSourceFile(dir1); 319 target = getTargetFile(dir2); 320 createDirectory(target); 321 entry = target.resolve("foo"); 322 createFile(entry); 323 try { 324 moveAndVerify(source, target); 325 throw new RuntimeException("FileAlreadyExistsException expected"); 326 } catch (FileAlreadyExistsException x) { 327 } 328 delete(entry); 329 delete(source); 330 delete(target); 331 332 /** 333 * Test atomic move of regular file (same file store) 334 */ 335 source = createSourceFile(dir1); 336 target = getTargetFile(dir1); 337 moveAndVerify(source, target, ATOMIC_MOVE); 338 delete(target); 339 340 /** 341 * Test atomic move of regular file (different file store) 342 */ 343 if (!sameDevice) { 344 source = createSourceFile(dir1); 345 target = getTargetFile(dir2); 346 try { 347 moveAndVerify(source, target, ATOMIC_MOVE); 348 throw new RuntimeException("AtomicMoveNotSupportedException expected"); 349 } catch (AtomicMoveNotSupportedException x) { 350 } 351 delete(source); 352 } 353 354 // -- directories -- 355 356 /* 357 * Test: move empty directory, target does not exist 358 */ 359 source = createSourceDirectory(dir1); 360 target = getTargetFile(dir2); 361 moveAndVerify(source, target); 362 delete(target); 363 364 /** 365 * Test: move empty directory, target exists 366 */ 367 source = createSourceDirectory(dir1); 368 target = getTargetFile(dir2); 369 createFile(target); 370 try { 371 moveAndVerify(source, target); 372 throw new RuntimeException("FileAlreadyExistsException expected"); 373 } catch (FileAlreadyExistsException x) { 374 } 375 delete(target); 376 createDirectory(target); 377 try { 378 moveAndVerify(source, target); 379 throw new RuntimeException("FileAlreadyExistsException expected"); 380 } catch (FileAlreadyExistsException x) { 381 } 382 delete(source); 383 delete(target); 384 385 /** 386 * Test: move empty directory, target does not exist 387 */ 388 source = createSourceDirectory(dir1); 389 target = getTargetFile(dir2); 390 moveAndVerify(source, target, REPLACE_EXISTING); 391 delete(target); 392 393 /** 394 * Test: move empty directory, target exists 395 */ 396 source = createSourceDirectory(dir1); 397 target = getTargetFile(dir2); 398 createFile(target); 399 moveAndVerify(source, target, REPLACE_EXISTING); 400 delete(target); 401 402 /** 403 * Test: move empty, target exists and is empty directory 404 */ 405 source = createSourceDirectory(dir1); 406 target = getTargetFile(dir2); 407 createDirectory(target); 408 moveAndVerify(source, target, REPLACE_EXISTING); 409 delete(target); 410 411 /** 412 * Test: move empty directory, target exists and is non-empty directory 413 */ 414 source = createSourceDirectory(dir1); 415 target = getTargetFile(dir2); 416 createDirectory(target); 417 entry = target.resolve("foo"); 418 createFile(entry); 419 try { 420 moveAndVerify(source, target, REPLACE_EXISTING); 421 throw new RuntimeException("DirectoryNotEmptyException expected"); 422 } catch (DirectoryNotEmptyException x) { 423 } 424 delete(entry); 425 delete(source); 426 delete(target); 427 428 /** 429 * Test: move non-empty directory (same file system) 430 */ 431 source = createSourceDirectory(dir1); 432 createFile(source.resolve("foo")); 433 target = getTargetFile(dir1); 434 moveAndVerify(source, target); 435 delete(target.resolve("foo")); 436 delete(target); 437 438 /** 439 * Test: move non-empty directory (different file store) 440 */ 441 if (!sameDevice) { 442 source = createSourceDirectory(dir1); 443 createFile(source.resolve("foo")); 444 target = getTargetFile(dir2); 445 try { 446 moveAndVerify(source, target); 447 throw new RuntimeException("IOException expected"); 448 } catch (IOException x) { 449 } 450 delete(source.resolve("foo")); 451 delete(source); 452 } 453 454 /** 455 * Test atomic move of directory (same file store) 456 */ 457 source = createSourceDirectory(dir1); 458 createFile(source.resolve("foo")); 459 target = getTargetFile(dir1); 460 moveAndVerify(source, target, ATOMIC_MOVE); 461 delete(target.resolve("foo")); 462 delete(target); 463 464 // -- symbolic links -- 465 466 /** 467 * Test: Move symbolic link to file, target does not exist 468 */ 469 if (supportsLinks) { 470 Path tmp = createSourceFile(dir1); 471 source = dir1.resolve("link"); 472 createSymbolicLink(source, tmp); 473 target = getTargetFile(dir2); 474 moveAndVerify(source, target); 475 delete(target); 476 delete(tmp); 477 } 478 479 /** 480 * Test: Move symbolic link to directory, target does not exist 481 */ 482 if (supportsLinks) { 483 source = dir1.resolve("link"); 484 createSymbolicLink(source, dir2); 485 target = getTargetFile(dir2); 486 moveAndVerify(source, target); 487 delete(target); 488 } 489 490 /** 491 * Test: Move broken symbolic link, target does not exists 492 */ 493 if (supportsLinks) { 494 Path tmp = Paths.get("doesnotexist"); 495 source = dir1.resolve("link"); 496 createSymbolicLink(source, tmp); 497 target = getTargetFile(dir2); 498 moveAndVerify(source, target); 499 delete(target); 500 } 501 502 /** 503 * Test: Move symbolic link, target exists 504 */ 505 if (supportsLinks) { 506 source = dir1.resolve("link"); 507 createSymbolicLink(source, dir2); 508 target = getTargetFile(dir2); 509 createFile(target); 510 try { 511 moveAndVerify(source, target); 512 throw new RuntimeException("FileAlreadyExistsException expected"); 513 } catch (FileAlreadyExistsException x) { 514 } 515 delete(source); 516 delete(target); 517 } 518 519 /** 520 * Test: Move regular file, target exists 521 */ 522 if (supportsLinks) { 523 source = dir1.resolve("link"); 524 createSymbolicLink(source, dir2); 525 target = getTargetFile(dir2); 526 createFile(target); 527 moveAndVerify(source, target, REPLACE_EXISTING); 528 delete(target); 529 } 530 531 /** 532 * Test: move symbolic link, target exists and is empty directory 533 */ 534 if (supportsLinks) { 535 source = dir1.resolve("link"); 536 createSymbolicLink(source, dir2); 537 target = getTargetFile(dir2); 538 createDirectory(target); 539 moveAndVerify(source, target, REPLACE_EXISTING); 540 delete(target); 541 } 542 543 /** 544 * Test: symbolic link, target exists and is non-empty directory 545 */ 546 if (supportsLinks) { 547 source = dir1.resolve("link"); 548 createSymbolicLink(source, dir2); 549 target = getTargetFile(dir2); 550 createDirectory(target); 551 entry = target.resolve("foo"); 552 createFile(entry); 553 try { 554 moveAndVerify(source, target); 555 throw new RuntimeException("FileAlreadyExistsException expected"); 556 } catch (FileAlreadyExistsException x) { 557 } 558 delete(entry); 559 delete(source); 560 delete(target); 561 } 562 563 /** 564 * Test atomic move of symbolic link (same file store) 565 */ 566 if (supportsLinks) { 567 source = dir1.resolve("link"); 568 createSymbolicLink(source, dir1); 569 target = getTargetFile(dir2); 570 createFile(target); 571 moveAndVerify(source, target, REPLACE_EXISTING); 572 delete(target); 573 } 574 575 // -- misc. tests -- 576 577 /** 578 * Test nulls 579 */ 580 source = createSourceFile(dir1); 581 target = getTargetFile(dir2); 582 try { 583 move(null, target); 584 throw new RuntimeException("NullPointerException expected"); 585 } catch (NullPointerException x) { } 586 try { 587 move(source, null); 588 throw new RuntimeException("NullPointerException expected"); 589 } catch (NullPointerException x) { } 590 try { 591 move(source, target, (CopyOption[])null); 592 throw new RuntimeException("NullPointerException expected"); 593 } catch (NullPointerException x) { } 594 try { 595 CopyOption[] opts = { REPLACE_EXISTING, null }; 596 move(source, target, opts); 597 throw new RuntimeException("NullPointerException expected"); 598 } catch (NullPointerException x) { } 599 delete(source); 600 601 /** 602 * Test UOE 603 */ 604 source = createSourceFile(dir1); 605 target = getTargetFile(dir2); 606 try { 607 move(source, target, new CopyOption() { }); 608 } catch (UnsupportedOperationException x) { } 609 try { 610 move(source, target, REPLACE_EXISTING, new CopyOption() { }); 611 } catch (UnsupportedOperationException x) { } 612 delete(source); 613 } 614 615 // copy source to target with verification copyAndVerify(Path source, Path target, CopyOption... options)616 static void copyAndVerify(Path source, Path target, CopyOption... options) 617 throws IOException 618 { 619 Path result = copy(source, target, options); 620 assertTrue(result == target); 621 622 // get attributes of source and target file to verify copy 623 boolean followLinks = true; 624 LinkOption[] linkOptions = new LinkOption[0]; 625 boolean copyAttributes = false; 626 for (CopyOption opt : options) { 627 if (opt == NOFOLLOW_LINKS) { 628 followLinks = false; 629 linkOptions = new LinkOption[] { NOFOLLOW_LINKS }; 630 } 631 if (opt == COPY_ATTRIBUTES) 632 copyAttributes = true; 633 } 634 BasicFileAttributes basicAttributes = 635 readAttributes(source, BasicFileAttributes.class, linkOptions); 636 637 // check hash if regular file 638 if (basicAttributes.isRegularFile()) 639 assertTrue(computeHash(source) == computeHash(target)); 640 641 // check link target if symbolic link 642 if (basicAttributes.isSymbolicLink()) 643 assert(readSymbolicLink(source).equals(readSymbolicLink(target))); 644 645 // check that attributes are copied 646 if (copyAttributes && followLinks) { 647 checkBasicAttributes(basicAttributes, 648 readAttributes(source, BasicFileAttributes.class, linkOptions)); 649 650 // verify other attributes when same provider 651 if (source.getFileSystem().provider() == target.getFileSystem().provider()) { 652 653 // check POSIX attributes are copied 654 String os = System.getProperty("os.name"); 655 if ((os.equals("SunOS") || os.equals("Linux") || os.endsWith("BSD")) && 656 testPosixAttributes) 657 { 658 checkPosixAttributes( 659 readAttributes(source, PosixFileAttributes.class, linkOptions), 660 readAttributes(target, PosixFileAttributes.class, linkOptions)); 661 } 662 663 // check DOS attributes are copied 664 if (os.startsWith("Windows")) { 665 checkDosAttributes( 666 readAttributes(source, DosFileAttributes.class, linkOptions), 667 readAttributes(target, DosFileAttributes.class, linkOptions)); 668 } 669 670 // check named attributes are copied 671 if (followLinks && 672 getFileStore(source).supportsFileAttributeView("xattr") && 673 getFileStore(target).supportsFileAttributeView("xattr")) 674 { 675 checkUserDefinedFileAttributes(readUserDefinedFileAttributes(source), 676 readUserDefinedFileAttributes(target)); 677 } 678 } 679 } 680 } 681 682 /** 683 * Tests all possible ways to invoke copy to copy a file to a file 684 */ testCopyFileToFile(Path dir1, Path dir2, boolean supportsLinks)685 static void testCopyFileToFile(Path dir1, Path dir2, boolean supportsLinks) 686 throws IOException 687 { 688 Path source, target, link, entry; 689 690 // -- regular file -- 691 692 /** 693 * Test: move regular file, target does not exist 694 */ 695 source = createSourceFile(dir1); 696 target = getTargetFile(dir2); 697 copyAndVerify(source, target); 698 delete(source); 699 delete(target); 700 701 /** 702 * Test: copy regular file, target exists 703 */ 704 source = createSourceFile(dir1); 705 target = getTargetFile(dir2); 706 createFile(target); 707 try { 708 copyAndVerify(source, target); 709 throw new RuntimeException("FileAlreadyExistsException expected"); 710 } catch (FileAlreadyExistsException x) { 711 } 712 delete(target); 713 createDirectory(target); 714 try { 715 copyAndVerify(source, target); 716 throw new RuntimeException("FileAlreadyExistsException expected"); 717 } catch (FileAlreadyExistsException x) { 718 } 719 delete(source); 720 delete(target); 721 722 /** 723 * Test: copy regular file, target does not exist 724 */ 725 source = createSourceFile(dir1); 726 target = getTargetFile(dir2); 727 copyAndVerify(source, target, REPLACE_EXISTING); 728 delete(source); 729 delete(target); 730 731 /** 732 * Test: copy regular file, target exists 733 */ 734 source = createSourceFile(dir1); 735 target = getTargetFile(dir2); 736 createFile(target); 737 copyAndVerify(source, target, REPLACE_EXISTING); 738 delete(source); 739 delete(target); 740 741 /** 742 * Test: copy regular file, target exists and is empty directory 743 */ 744 source = createSourceFile(dir1); 745 target = getTargetFile(dir2); 746 createDirectory(target); 747 copyAndVerify(source, target, REPLACE_EXISTING); 748 delete(source); 749 delete(target); 750 751 /** 752 * Test: copy regular file, target exists and is non-empty directory 753 */ 754 source = createSourceFile(dir1); 755 target = getTargetFile(dir2); 756 createDirectory(target); 757 entry = target.resolve("foo"); 758 createFile(entry); 759 try { 760 copyAndVerify(source, target); 761 throw new RuntimeException("FileAlreadyExistsException expected"); 762 } catch (FileAlreadyExistsException x) { 763 } 764 delete(entry); 765 delete(source); 766 delete(target); 767 768 /** 769 * Test: copy regular file + attributes 770 */ 771 source = createSourceFile(dir1); 772 target = getTargetFile(dir2); 773 copyAndVerify(source, target, COPY_ATTRIBUTES); 774 delete(source); 775 delete(target); 776 777 778 // -- directory -- 779 780 /* 781 * Test: copy directory, target does not exist 782 */ 783 source = createSourceDirectory(dir1); 784 target = getTargetFile(dir2); 785 copyAndVerify(source, target); 786 delete(source); 787 delete(target); 788 789 /** 790 * Test: copy directory, target exists 791 */ 792 source = createSourceDirectory(dir1); 793 target = getTargetFile(dir2); 794 createFile(target); 795 try { 796 copyAndVerify(source, target); 797 throw new RuntimeException("FileAlreadyExistsException expected"); 798 } catch (FileAlreadyExistsException x) { 799 } 800 delete(target); 801 createDirectory(target); 802 try { 803 copyAndVerify(source, target); 804 throw new RuntimeException("FileAlreadyExistsException expected"); 805 } catch (FileAlreadyExistsException x) { 806 } 807 delete(source); 808 delete(target); 809 810 /** 811 * Test: copy directory, target does not exist 812 */ 813 source = createSourceDirectory(dir1); 814 target = getTargetFile(dir2); 815 copyAndVerify(source, target, REPLACE_EXISTING); 816 delete(source); 817 delete(target); 818 819 /** 820 * Test: copy directory, target exists 821 */ 822 source = createSourceDirectory(dir1); 823 target = getTargetFile(dir2); 824 createFile(target); 825 copyAndVerify(source, target, REPLACE_EXISTING); 826 delete(source); 827 delete(target); 828 829 /** 830 * Test: copy directory, target exists and is empty directory 831 */ 832 source = createSourceDirectory(dir1); 833 target = getTargetFile(dir2); 834 createDirectory(target); 835 copyAndVerify(source, target, REPLACE_EXISTING); 836 delete(source); 837 delete(target); 838 839 /** 840 * Test: copy directory, target exists and is non-empty directory 841 */ 842 source = createSourceDirectory(dir1); 843 target = getTargetFile(dir2); 844 createDirectory(target); 845 entry = target.resolve("foo"); 846 createFile(entry); 847 try { 848 copyAndVerify(source, target, REPLACE_EXISTING); 849 throw new RuntimeException("DirectoryNotEmptyException expected"); 850 } catch (DirectoryNotEmptyException x) { 851 } 852 delete(entry); 853 delete(source); 854 delete(target); 855 856 /* 857 * Test: copy directory + attributes 858 */ 859 source = createSourceDirectory(dir1); 860 target = getTargetFile(dir2); 861 copyAndVerify(source, target, COPY_ATTRIBUTES); 862 delete(source); 863 delete(target); 864 865 // -- symbolic links -- 866 867 /** 868 * Test: Follow link 869 */ 870 if (supportsLinks) { 871 source = createSourceFile(dir1); 872 link = dir1.resolve("link"); 873 createSymbolicLink(link, source); 874 target = getTargetFile(dir2); 875 copyAndVerify(link, target); 876 delete(link); 877 delete(source); 878 } 879 880 /** 881 * Test: Copy link (to file) 882 */ 883 if (supportsLinks) { 884 source = createSourceFile(dir1); 885 link = dir1.resolve("link"); 886 createSymbolicLink(link, source); 887 target = getTargetFile(dir2); 888 copyAndVerify(link, target, NOFOLLOW_LINKS); 889 delete(link); 890 delete(source); 891 } 892 893 /** 894 * Test: Copy link (to directory) 895 */ 896 if (supportsLinks) { 897 source = dir1.resolve("mydir"); 898 createDirectory(source); 899 link = dir1.resolve("link"); 900 createSymbolicLink(link, source); 901 target = getTargetFile(dir2); 902 copyAndVerify(link, target, NOFOLLOW_LINKS); 903 delete(link); 904 delete(source); 905 } 906 907 /** 908 * Test: Copy broken link 909 */ 910 if (supportsLinks) { 911 assertTrue(notExists(source)); 912 link = dir1.resolve("link"); 913 createSymbolicLink(link, source); 914 target = getTargetFile(dir2); 915 copyAndVerify(link, target, NOFOLLOW_LINKS); 916 delete(link); 917 } 918 919 /** 920 * Test: Copy link to UNC (Windows only) 921 */ 922 if (supportsLinks && 923 System.getProperty("os.name").startsWith("Windows")) 924 { 925 Path unc = Paths.get("\\\\rialto\\share\\file"); 926 link = dir1.resolve("link"); 927 createSymbolicLink(link, unc); 928 target = getTargetFile(dir2); 929 copyAndVerify(link, target, NOFOLLOW_LINKS); 930 delete(link); 931 } 932 933 // -- misc. tests -- 934 935 /** 936 * Test nulls 937 */ 938 source = createSourceFile(dir1); 939 target = getTargetFile(dir2); 940 try { 941 copy(source, null); 942 throw new RuntimeException("NullPointerException expected"); 943 } catch (NullPointerException x) { } 944 try { 945 copy(source, target, (CopyOption[])null); 946 throw new RuntimeException("NullPointerException expected"); 947 } catch (NullPointerException x) { } 948 try { 949 CopyOption[] opts = { REPLACE_EXISTING, null }; 950 copy(source, target, opts); 951 throw new RuntimeException("NullPointerException expected"); 952 } catch (NullPointerException x) { } 953 delete(source); 954 955 /** 956 * Test UOE 957 */ 958 source = createSourceFile(dir1); 959 target = getTargetFile(dir2); 960 try { 961 copy(source, target, new CopyOption() { }); 962 } catch (UnsupportedOperationException x) { } 963 try { 964 copy(source, target, REPLACE_EXISTING, new CopyOption() { }); 965 } catch (UnsupportedOperationException x) { } 966 delete(source); 967 } 968 969 /** 970 * Test copy from an input stream to a file 971 */ testCopyInputStreamToFile()972 static void testCopyInputStreamToFile() throws IOException { 973 testCopyInputStreamToFile(0); 974 for (int i=0; i<100; i++) { 975 testCopyInputStreamToFile(rand.nextInt(32000)); 976 } 977 978 // FileAlreadyExistsException 979 Path target = createTempFile("blah", null); 980 try { 981 InputStream in = new ByteArrayInputStream(new byte[0]); 982 try { 983 copy(in, target); 984 throw new RuntimeException("FileAlreadyExistsException expected"); 985 } catch (FileAlreadyExistsException ignore) { } 986 } finally { 987 delete(target); 988 } 989 Path tmpdir = createTempDirectory("blah"); 990 try { 991 if (TestUtil.supportsLinks(tmpdir)) { 992 Path link = createSymbolicLink(tmpdir.resolve("link"), 993 tmpdir.resolve("target")); 994 try { 995 InputStream in = new ByteArrayInputStream(new byte[0]); 996 try { 997 copy(in, link); 998 throw new RuntimeException("FileAlreadyExistsException expected"); 999 } catch (FileAlreadyExistsException ignore) { } 1000 } finally { 1001 delete(link); 1002 } 1003 } 1004 } finally { 1005 delete(tmpdir); 1006 } 1007 1008 1009 // nulls 1010 try { 1011 copy((InputStream)null, target); 1012 throw new RuntimeException("NullPointerException expected"); 1013 } catch (NullPointerException ignore) { } 1014 try { 1015 copy(new ByteArrayInputStream(new byte[0]), (Path)null); 1016 throw new RuntimeException("NullPointerException expected"); 1017 } catch (NullPointerException ignore) { } 1018 } 1019 testCopyInputStreamToFile(int size)1020 static void testCopyInputStreamToFile(int size) throws IOException { 1021 Path tmpdir = createTempDirectory("blah"); 1022 Path source = tmpdir.resolve("source"); 1023 Path target = tmpdir.resolve("target"); 1024 try { 1025 boolean testReplaceExisting = rand.nextBoolean(); 1026 1027 // create source file 1028 byte[] b = new byte[size]; 1029 rand.nextBytes(b); 1030 write(source, b); 1031 1032 // target file might already exist 1033 if (testReplaceExisting && rand.nextBoolean()) { 1034 write(target, new byte[rand.nextInt(512)]); 1035 } 1036 1037 // copy from stream to file 1038 InputStream in = new FileInputStream(source.toFile()); 1039 try { 1040 long n; 1041 if (testReplaceExisting) { 1042 n = copy(in, target, StandardCopyOption.REPLACE_EXISTING); 1043 } else { 1044 n = copy(in, target); 1045 } 1046 assertTrue(in.read() == -1); // EOF 1047 assertTrue(n == size); 1048 assertTrue(size(target) == size); 1049 } finally { 1050 in.close(); 1051 } 1052 1053 // check file 1054 byte[] read = readAllBytes(target); 1055 assertTrue(Arrays.equals(read, b)); 1056 1057 } finally { 1058 deleteIfExists(source); 1059 deleteIfExists(target); 1060 delete(tmpdir); 1061 } 1062 } 1063 1064 /** 1065 * Test copy from file to output stream 1066 */ testCopyFileToOuputStream()1067 static void testCopyFileToOuputStream() throws IOException { 1068 testCopyFileToOuputStream(0); 1069 for (int i=0; i<100; i++) { 1070 testCopyFileToOuputStream(rand.nextInt(32000)); 1071 } 1072 1073 // nulls 1074 try { 1075 copy((Path)null, new ByteArrayOutputStream()); 1076 throw new RuntimeException("NullPointerException expected"); 1077 } catch (NullPointerException ignore) { } 1078 try { 1079 Path source = createTempFile("blah", null); 1080 delete(source); 1081 copy(source, (OutputStream)null); 1082 throw new RuntimeException("NullPointerException expected"); 1083 } catch (NullPointerException ignore) { } 1084 } 1085 testCopyFileToOuputStream(int size)1086 static void testCopyFileToOuputStream(int size) throws IOException { 1087 Path source = createTempFile("blah", null); 1088 try { 1089 byte[] b = new byte[size]; 1090 rand.nextBytes(b); 1091 write(source, b); 1092 1093 ByteArrayOutputStream out = new ByteArrayOutputStream(); 1094 1095 long n = copy(source, out); 1096 assertTrue(n == size); 1097 assertTrue(out.size() == size); 1098 1099 byte[] read = out.toByteArray(); 1100 assertTrue(Arrays.equals(read, b)); 1101 1102 // check output stream is open 1103 out.write(0); 1104 assertTrue(out.size() == size+1); 1105 } finally { 1106 delete(source); 1107 } 1108 } 1109 assertTrue(boolean value)1110 static void assertTrue(boolean value) { 1111 if (!value) 1112 throw new RuntimeException("Assertion failed"); 1113 } 1114 1115 // computes simple hash of the given file computeHash(Path file)1116 static int computeHash(Path file) throws IOException { 1117 int h = 0; 1118 1119 try (InputStream in = newInputStream(file)) { 1120 byte[] buf = new byte[1024]; 1121 int n; 1122 do { 1123 n = in.read(buf); 1124 for (int i=0; i<n; i++) { 1125 h = 31*h + (buf[i] & 0xff); 1126 } 1127 } while (n > 0); 1128 } 1129 return h; 1130 } 1131 1132 // create file of random size in given directory createSourceFile(Path dir)1133 static Path createSourceFile(Path dir) throws IOException { 1134 String name = "source" + Integer.toString(rand.nextInt()); 1135 Path file = dir.resolve(name); 1136 createFile(file); 1137 byte[] bytes = new byte[rand.nextInt(128*1024)]; 1138 rand.nextBytes(bytes); 1139 try (OutputStream out = newOutputStream(file)) { 1140 out.write(bytes); 1141 } 1142 randomizeAttributes(file); 1143 return file; 1144 } 1145 1146 // create directory in the given directory createSourceDirectory(Path dir)1147 static Path createSourceDirectory(Path dir) throws IOException { 1148 String name = "sourcedir" + Integer.toString(rand.nextInt()); 1149 Path subdir = dir.resolve(name); 1150 createDirectory(subdir); 1151 randomizeAttributes(subdir); 1152 return subdir; 1153 } 1154 1155 // "randomize" the file attributes of the given file. randomizeAttributes(Path file)1156 static void randomizeAttributes(Path file) throws IOException { 1157 String os = System.getProperty("os.name"); 1158 boolean isWindows = os.startsWith("Windows"); 1159 boolean isUnix = os.equals("SunOS") || os.equals("Linux") || os.endsWith("BSD"); 1160 boolean isDirectory = isDirectory(file, NOFOLLOW_LINKS); 1161 1162 if (isUnix) { 1163 Set<PosixFilePermission> perms = 1164 getPosixFilePermissions(file, NOFOLLOW_LINKS); 1165 PosixFilePermission[] toChange = { 1166 PosixFilePermission.GROUP_READ, 1167 PosixFilePermission.GROUP_WRITE, 1168 PosixFilePermission.GROUP_EXECUTE, 1169 PosixFilePermission.OTHERS_READ, 1170 PosixFilePermission.OTHERS_WRITE, 1171 PosixFilePermission.OTHERS_EXECUTE 1172 }; 1173 for (PosixFilePermission perm: toChange) { 1174 if (heads()) { 1175 perms.add(perm); 1176 } else { 1177 perms.remove(perm); 1178 } 1179 } 1180 setPosixFilePermissions(file, perms); 1181 } 1182 1183 if (isWindows) { 1184 DosFileAttributeView view = 1185 getFileAttributeView(file, DosFileAttributeView.class, NOFOLLOW_LINKS); 1186 // only set or unset the hidden attribute 1187 view.setHidden(heads()); 1188 } 1189 1190 boolean addUserDefinedFileAttributes = heads() && 1191 getFileStore(file).supportsFileAttributeView("xattr"); 1192 1193 // remove this when copying a direcory copies its named streams 1194 if (isWindows && isDirectory) addUserDefinedFileAttributes = false; 1195 1196 if (addUserDefinedFileAttributes) { 1197 UserDefinedFileAttributeView view = 1198 getFileAttributeView(file, UserDefinedFileAttributeView.class); 1199 int n = rand.nextInt(16); 1200 while (n > 0) { 1201 byte[] value = new byte[1 + rand.nextInt(100)]; 1202 view.write("user." + Integer.toString(n), ByteBuffer.wrap(value)); 1203 n--; 1204 } 1205 } 1206 } 1207 1208 // create name for file in given directory getTargetFile(Path dir)1209 static Path getTargetFile(Path dir) throws IOException { 1210 String name = "target" + Integer.toString(rand.nextInt()); 1211 return dir.resolve(name); 1212 } 1213 } 1214