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