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