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