--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/Path/CopyAndMove.java Sun Feb 15 12:25:54 2009 +0000
@@ -0,0 +1,983 @@
+/*
+ * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/* @test
+ * @bug 4313887
+ * @summary Unit test for java.nio.file.Path copyTo/moveTo methods
+ * @library ..
+ */
+
+import java.nio.ByteBuffer;
+import java.nio.file.*;
+import static java.nio.file.StandardCopyOption.*;
+import static java.nio.file.LinkOption.*;
+import java.nio.file.attribute.*;
+import java.io.*;
+import java.util.*;
+
+public class CopyAndMove {
+ static final Random rand = new Random();
+ static boolean heads() { return rand.nextBoolean(); }
+ static boolean supportsLinks;
+
+ public static void main(String[] args) throws Exception {
+ Path dir1 = TestUtil.createTemporaryDirectory();
+ try {
+ supportsLinks = TestUtil.supportsLinks(dir1);
+
+ // Exercise copyTo
+ doCopyTests(dir1);
+
+ // Exercise moveTo
+ // if test.dir differs to temporary file system then can test
+ // moving between devices
+ String testDir = System.getProperty("test.dir");
+ Path dir2 = (testDir != null) ? Paths.get(testDir) : dir1;
+ doMoveTests(dir1, dir2);
+
+ } finally {
+ TestUtil.removeAll(dir1);
+ }
+ }
+
+ static void checkBasicAttributes(BasicFileAttributes attrs1,
+ BasicFileAttributes attrs2)
+ {
+ // check file type
+ assertTrue(attrs1.isRegularFile() == attrs2.isRegularFile());
+ assertTrue(attrs1.isDirectory() == attrs2.isDirectory());
+ assertTrue(attrs1.isSymbolicLink() == attrs2.isSymbolicLink());
+ assertTrue(attrs1.isOther() == attrs2.isOther());
+
+ // check last modified time (assume millisecond precision)
+ long time1 = attrs1.resolution().toMillis(attrs1.lastModifiedTime());
+ long time2 = attrs1.resolution().toMillis(attrs2.lastModifiedTime());
+ assertTrue(time1 == time2);
+
+ // check size
+ if (attrs1.isRegularFile())
+ assertTrue(attrs1.size() == attrs2.size());
+ }
+
+ static void checkPosixAttributes(PosixFileAttributes attrs1,
+ PosixFileAttributes attrs2)
+ {
+ assertTrue(attrs1.permissions().equals(attrs2.permissions()));
+ assertTrue(attrs1.owner().equals(attrs2.owner()));
+ assertTrue(attrs1.group().equals(attrs2.group()));
+ }
+
+ static void checkDosAttributes(DosFileAttributes attrs1,
+ DosFileAttributes attrs2)
+ {
+ assertTrue(attrs1.isReadOnly() == attrs2.isReadOnly());
+ assertTrue(attrs1.isHidden() == attrs2.isHidden());
+ assertTrue(attrs1.isArchive() == attrs2.isArchive());
+ assertTrue(attrs1.isSystem() == attrs2.isSystem());
+ }
+
+ static void checkUserDefinedFileAttributes(Map<String,ByteBuffer> attrs1,
+ Map<String,ByteBuffer> attrs2)
+ {
+ assert attrs1.size() == attrs2.size();
+ for (String name: attrs1.keySet()) {
+ ByteBuffer bb1 = attrs1.get(name);
+ ByteBuffer bb2 = attrs2.get(name);
+ assertTrue(bb2 != null);
+ assertTrue(bb1.equals(bb2));
+ }
+ }
+
+ static Map<String,ByteBuffer> readUserDefinedFileAttributes(Path file)
+ throws IOException
+ {
+ UserDefinedFileAttributeView view = file
+ .getFileAttributeView(UserDefinedFileAttributeView.class);
+ Map<String,ByteBuffer> result = new HashMap<String,ByteBuffer>();
+ for (String name: view.list()) {
+ int size = view.size(name);
+ ByteBuffer bb = ByteBuffer.allocate(size);
+ int n = view.read(name, bb);
+ assertTrue(n == size);
+ bb.flip();
+ result.put(name, bb);
+ }
+ return result;
+ }
+
+ // move source to target with verification
+ static void moveAndVerify(Path source, Path target, CopyOption... options)
+ throws IOException
+ {
+ // read attributes before file is moved
+ BasicFileAttributes basicAttributes = null;
+ PosixFileAttributes posixAttributes = null;
+ DosFileAttributes dosAttributes = null;
+ Map<String,ByteBuffer> namedAttributes = null;
+
+ // get file attributes of source file
+ String os = System.getProperty("os.name");
+ if (os.equals("SunOS") || os.equals("Linux")) {
+ posixAttributes = Attributes.readPosixFileAttributes(source, NOFOLLOW_LINKS);
+ basicAttributes = posixAttributes;
+ }
+ if (os.startsWith("Windows")) {
+ dosAttributes = Attributes.readDosFileAttributes(source, NOFOLLOW_LINKS);
+ basicAttributes = dosAttributes;
+ }
+ if (basicAttributes == null)
+ basicAttributes = Attributes.readBasicFileAttributes(source, NOFOLLOW_LINKS);
+
+ // hash file contents if regular file
+ int hash = (basicAttributes.isRegularFile()) ? computeHash(source) : 0;
+
+ // record link target if symbolic link
+ Path linkTarget = null;
+ if (basicAttributes.isSymbolicLink())
+ linkTarget = source.readSymbolicLink();
+
+ // read named attributes if available (and file is not a sym link)
+ if (!basicAttributes.isSymbolicLink() &&
+ source.getFileStore().supportsFileAttributeView("xattr"))
+ {
+ namedAttributes = readUserDefinedFileAttributes(source);
+ }
+
+ // move file
+ source.moveTo(target, options);
+
+ // verify source does not exist
+ assertTrue(source.notExists());
+
+ // verify file contents
+ if (basicAttributes.isRegularFile()) {
+ if (computeHash(target) != hash)
+ throw new RuntimeException("Failed to verify move of regular file");
+ }
+
+ // verify link target
+ if (basicAttributes.isSymbolicLink()) {
+ if (!target.readSymbolicLink().equals(linkTarget))
+ throw new RuntimeException("Failed to verify move of symbolic link");
+ }
+
+ // verify basic attributes
+ checkBasicAttributes(basicAttributes,
+ Attributes.readBasicFileAttributes(target, NOFOLLOW_LINKS));
+
+ // verify POSIX attributes
+ if (posixAttributes != null && !basicAttributes.isSymbolicLink()) {
+ checkPosixAttributes(posixAttributes,
+ Attributes.readPosixFileAttributes(target, NOFOLLOW_LINKS));
+ }
+
+ // verify DOS attributes
+ if (dosAttributes != null && !basicAttributes.isSymbolicLink()) {
+ checkDosAttributes(dosAttributes,
+ Attributes.readDosFileAttributes(target, NOFOLLOW_LINKS));
+ }
+
+ // verify named attributes
+ if (namedAttributes != null &&
+ target.getFileStore().supportsFileAttributeView("xattr"))
+ {
+ checkUserDefinedFileAttributes(namedAttributes, readUserDefinedFileAttributes(target));
+ }
+ }
+
+ /**
+ * Tests all possible ways to invoke moveTo
+ */
+ static void doMoveTests(Path dir1, Path dir2) throws IOException {
+ Path source, target, entry;
+
+ boolean sameDevice = dir1.getFileStore().equals(dir2.getFileStore());
+
+ // -- regular file --
+
+ /**
+ * Test: move regular file, target does not exist
+ */
+ source = createSourceFile(dir1);
+ target = getTargetFile(dir1);
+ moveAndVerify(source, target);
+ target.delete();
+
+ /**
+ * Test: move regular file, target exists
+ */
+ source = createSourceFile(dir1);
+ target = getTargetFile(dir1).createFile();
+ try {
+ moveAndVerify(source, target);
+ throw new RuntimeException("FileAlreadyExistsException expected");
+ } catch (FileAlreadyExistsException x) {
+ }
+ target.delete();
+ target.createDirectory();
+ try {
+ moveAndVerify(source, target);
+ throw new RuntimeException("FileAlreadyExistsException expected");
+ } catch (FileAlreadyExistsException x) {
+ }
+ source.delete();
+ target.delete();
+
+ /**
+ * Test: move regular file, target does not exist
+ */
+ source = createSourceFile(dir1);
+ target = getTargetFile(dir1);
+ moveAndVerify(source, target, REPLACE_EXISTING);
+ target.delete();
+
+ /**
+ * Test: move regular file, target exists
+ */
+ source = createSourceFile(dir1);
+ target = getTargetFile(dir1).createFile();
+ moveAndVerify(source, target, REPLACE_EXISTING);
+ target.delete();
+
+ /**
+ * Test: move regular file, target exists and is empty directory
+ */
+ source = createSourceFile(dir1);
+ target = getTargetFile(dir1).createDirectory();
+ moveAndVerify(source, target, REPLACE_EXISTING);
+ target.delete();
+
+ /**
+ * Test: move regular file, target exists and is non-empty directory
+ */
+ source = createSourceFile(dir1);
+ target = getTargetFile(dir1).createDirectory();
+ entry = target.resolve("foo").createFile();
+ try {
+ moveAndVerify(source, target);
+ throw new RuntimeException("FileAlreadyExistsException expected");
+ } catch (FileAlreadyExistsException x) {
+ }
+ entry.delete();
+ source.delete();
+ target.delete();
+
+ /**
+ * Test atomic move of regular file (same file store)
+ */
+ source = createSourceFile(dir1);
+ target = getTargetFile(dir1);
+ moveAndVerify(source, target, ATOMIC_MOVE);
+ target.delete();
+
+ /**
+ * Test atomic move of regular file (different file store)
+ */
+ if (!sameDevice) {
+ source = createSourceFile(dir1);
+ target = getTargetFile(dir2);
+ try {
+ moveAndVerify(source, target, ATOMIC_MOVE);
+ throw new RuntimeException("AtomicMoveNotSupportedException expected");
+ } catch (AtomicMoveNotSupportedException x) {
+ }
+ source.delete();
+ }
+
+ // -- directories --
+
+ /*
+ * Test: move empty directory, target does not exist
+ */
+ source = createSourceDirectory(dir1);
+ target = getTargetFile(dir1);
+ moveAndVerify(source, target);
+ target.delete();
+
+ /**
+ * Test: move empty directory, target exists
+ */
+ source = createSourceDirectory(dir1);
+ target = getTargetFile(dir1).createFile();
+ try {
+ moveAndVerify(source, target);
+ throw new RuntimeException("FileAlreadyExistsException expected");
+ } catch (FileAlreadyExistsException x) {
+ }
+ target.delete();
+ target.createDirectory();
+ try {
+ moveAndVerify(source, target);
+ throw new RuntimeException("FileAlreadyExistsException expected");
+ } catch (FileAlreadyExistsException x) {
+ }
+ source.delete();
+ target.delete();
+
+ /**
+ * Test: move empty directory, target does not exist
+ */
+ source = createSourceDirectory(dir1);
+ target = getTargetFile(dir1);
+ moveAndVerify(source, target, REPLACE_EXISTING);
+ target.delete();
+
+ /**
+ * Test: move empty directory, target exists
+ */
+ source = createSourceDirectory(dir1);
+ target = getTargetFile(dir1).createFile();
+ moveAndVerify(source, target, REPLACE_EXISTING);
+ target.delete();
+
+ /**
+ * Test: move empty, target exists and is empty directory
+ */
+ source = createSourceDirectory(dir1);
+ target = getTargetFile(dir1).createDirectory();
+ moveAndVerify(source, target, REPLACE_EXISTING);
+ target.delete();
+
+ /**
+ * Test: move empty directory, target exists and is non-empty directory
+ */
+ source = createSourceDirectory(dir1);
+ target = getTargetFile(dir1).createDirectory();
+ entry = target.resolve("foo").createFile();
+ try {
+ moveAndVerify(source, target, REPLACE_EXISTING);
+ throw new RuntimeException("FileAlreadyExistsException expected");
+ } catch (FileAlreadyExistsException x) {
+ }
+ entry.delete();
+ source.delete();
+ target.delete();
+
+ /**
+ * Test: move non-empty directory (same file system)
+ */
+ source = createSourceDirectory(dir1);
+ source.resolve("foo").createFile();
+ target = getTargetFile(dir1);
+ moveAndVerify(source, target);
+ target.resolve("foo").delete();
+ target.delete();
+
+ /**
+ * Test: move non-empty directory (different file store)
+ */
+ if (!sameDevice) {
+ source = createSourceDirectory(dir1);
+ source.resolve("foo").createFile();
+ target = getTargetFile(dir2);
+ try {
+ moveAndVerify(source, target);
+ throw new RuntimeException("IOException expected");
+ } catch (IOException x) {
+ }
+ source.resolve("foo").delete();
+ source.delete();
+ }
+
+ /**
+ * Test atomic move of directory (same file store)
+ */
+ source = createSourceDirectory(dir1);
+ source.resolve("foo").createFile();
+ target = getTargetFile(dir1);
+ moveAndVerify(source, target, ATOMIC_MOVE);
+ target.resolve("foo").delete();
+ target.delete();
+
+ // -- symbolic links --
+
+ /**
+ * Test: Move symbolic link to file, target does not exist
+ */
+ if (supportsLinks) {
+ Path tmp = createSourceFile(dir1);
+ source = dir1.resolve("link").createSymbolicLink(tmp);
+ target = getTargetFile(dir1);
+ moveAndVerify(source, target);
+ target.delete();
+ tmp.delete();
+ }
+
+ /**
+ * Test: Move symbolic link to directory, target does not exist
+ */
+ if (supportsLinks) {
+ source = dir1.resolve("link").createSymbolicLink(dir2);
+ target = getTargetFile(dir1);
+ moveAndVerify(source, target);
+ target.delete();
+ }
+
+ /**
+ * Test: Move broken symbolic link, target does not exists
+ */
+ if (supportsLinks) {
+ Path tmp = Paths.get("doesnotexist");
+ source = dir1.resolve("link").createSymbolicLink(tmp);
+ target = getTargetFile(dir1);
+ moveAndVerify(source, target);
+ target.delete();
+ }
+
+ /**
+ * Test: Move symbolic link, target exists
+ */
+ if (supportsLinks) {
+ source = dir1.resolve("link").createSymbolicLink(dir2);
+ target = getTargetFile(dir1).createFile();
+ try {
+ moveAndVerify(source, target);
+ throw new RuntimeException("FileAlreadyExistsException expected");
+ } catch (FileAlreadyExistsException x) {
+ }
+ source.delete();
+ target.delete();
+ }
+
+ /**
+ * Test: Move regular file, target exists
+ */
+ if (supportsLinks) {
+ source = dir1.resolve("link").createSymbolicLink(dir2);
+ target = getTargetFile(dir1).createFile();
+ moveAndVerify(source, target, REPLACE_EXISTING);
+ target.delete();
+ }
+
+ /**
+ * Test: move symbolic link, target exists and is empty directory
+ */
+ if (supportsLinks) {
+ source = dir1.resolve("link").createSymbolicLink(dir2);
+ target = getTargetFile(dir1).createDirectory();
+ moveAndVerify(source, target, REPLACE_EXISTING);
+ target.delete();
+ }
+
+ /**
+ * Test: symbolic link, target exists and is non-empty directory
+ */
+ if (supportsLinks) {
+ source = dir1.resolve("link").createSymbolicLink(dir2);
+ target = getTargetFile(dir1).createDirectory();
+ entry = target.resolve("foo").createFile();
+ try {
+ moveAndVerify(source, target);
+ throw new RuntimeException("FileAlreadyExistsException expected");
+ } catch (FileAlreadyExistsException x) {
+ }
+ entry.delete();
+ source.delete();
+ target.delete();
+ }
+
+ /**
+ * Test atomic move of symbolic link (same file store)
+ */
+ if (supportsLinks) {
+ source = dir1.resolve("link").createSymbolicLink(dir1);
+ target = getTargetFile(dir1).createFile();
+ moveAndVerify(source, target, REPLACE_EXISTING);
+ target.delete();
+ }
+
+ // -- misc. tests --
+
+ /**
+ * Test nulls
+ */
+ source = createSourceFile(dir1);
+ target = getTargetFile(dir1);
+ try {
+ source.moveTo(null);
+ throw new RuntimeException("NullPointerException expected");
+ } catch (NullPointerException x) { }
+ try {
+ source.moveTo(target, (CopyOption[])null);
+ throw new RuntimeException("NullPointerException expected");
+ } catch (NullPointerException x) { }
+ try {
+ CopyOption[] opts = { REPLACE_EXISTING, null };
+ source.moveTo(target, opts);
+ throw new RuntimeException("NullPointerException expected");
+ } catch (NullPointerException x) { }
+ source.delete();
+
+ /**
+ * Test UOE
+ */
+ source = createSourceFile(dir1);
+ target = getTargetFile(dir1);
+ try {
+ source.moveTo(target, new CopyOption() { });
+ } catch (UnsupportedOperationException x) { }
+ try {
+ source.moveTo(target, REPLACE_EXISTING, new CopyOption() { });
+ } catch (UnsupportedOperationException x) { }
+ source.delete();
+ }
+
+ // copy source to target with verification
+ static void copyAndVerify(Path source, Path target, CopyOption... options)
+ throws IOException
+ {
+ source.copyTo(target, options);
+
+ // get attributes of source and target file to verify copy
+ boolean followLinks = true;
+ LinkOption[] linkOptions = new LinkOption[0];
+ boolean copyAttributes = false;
+ for (CopyOption opt : options) {
+ if (opt == NOFOLLOW_LINKS) {
+ followLinks = false;
+ linkOptions = new LinkOption[] { NOFOLLOW_LINKS };
+ }
+ if (opt == COPY_ATTRIBUTES)
+ copyAttributes = true;
+ }
+ BasicFileAttributes basicAttributes = Attributes
+ .readBasicFileAttributes(source, linkOptions);
+
+ // check hash if regular file
+ if (basicAttributes.isRegularFile())
+ assertTrue(computeHash(source) == computeHash(target));
+
+ // check link target if symbolic link
+ if (basicAttributes.isSymbolicLink())
+ assert( source.readSymbolicLink().equals(target.readSymbolicLink()));
+
+ // check that attributes are copied
+ if (copyAttributes && followLinks) {
+ checkBasicAttributes(basicAttributes,
+ Attributes.readBasicFileAttributes(source, linkOptions));
+
+ // check POSIX attributes are copied
+ String os = System.getProperty("os.name");
+ if (os.equals("SunOS") || os.equals("Linux")) {
+ checkPosixAttributes(
+ Attributes.readPosixFileAttributes(source, linkOptions),
+ Attributes.readPosixFileAttributes(target, linkOptions));
+ }
+
+ // check DOS attributes are copied
+ if (os.startsWith("Windows")) {
+ checkDosAttributes(
+ Attributes.readDosFileAttributes(source, linkOptions),
+ Attributes.readDosFileAttributes(target, linkOptions));
+ }
+
+ // check named attributes are copied
+ if (followLinks &&
+ source.getFileStore().supportsFileAttributeView("xattr") &&
+ target.getFileStore().supportsFileAttributeView("xattr"))
+ {
+ checkUserDefinedFileAttributes(readUserDefinedFileAttributes(source),
+ readUserDefinedFileAttributes(target));
+ }
+ }
+ }
+
+ /**
+ * Tests all possible ways to invoke copyTo
+ */
+ static void doCopyTests(Path dir) throws IOException {
+ Path source, target, link, entry;
+
+ // -- regular file --
+
+ /**
+ * Test: move regular file, target does not exist
+ */
+ source = createSourceFile(dir);
+ target = getTargetFile(dir);
+ copyAndVerify(source, target);
+ source.delete();
+ target.delete();
+
+ /**
+ * Test: copy regular file, target exists
+ */
+ source = createSourceFile(dir);
+ target = getTargetFile(dir).createFile();
+ try {
+ copyAndVerify(source, target);
+ throw new RuntimeException("FileAlreadyExistsException expected");
+ } catch (FileAlreadyExistsException x) {
+ }
+ target.delete();
+ target.createDirectory();
+ try {
+ copyAndVerify(source, target);
+ throw new RuntimeException("FileAlreadyExistsException expected");
+ } catch (FileAlreadyExistsException x) {
+ }
+ source.delete();
+ target.delete();
+
+ /**
+ * Test: copy regular file, target does not exist
+ */
+ source = createSourceFile(dir);
+ target = getTargetFile(dir);
+ copyAndVerify(source, target, REPLACE_EXISTING);
+ source.delete();
+ target.delete();
+
+ /**
+ * Test: copy regular file, target exists
+ */
+ source = createSourceFile(dir);
+ target = getTargetFile(dir).createFile();
+ copyAndVerify(source, target, REPLACE_EXISTING);
+ source.delete();
+ target.delete();
+
+ /**
+ * Test: copy regular file, target exists and is empty directory
+ */
+ source = createSourceFile(dir);
+ target = getTargetFile(dir).createDirectory();
+ copyAndVerify(source, target, REPLACE_EXISTING);
+ source.delete();
+ target.delete();
+
+ /**
+ * Test: copy regular file, target exists and is non-empty directory
+ */
+ source = createSourceFile(dir);
+ target = getTargetFile(dir).createDirectory();
+ entry = target.resolve("foo").createFile();
+ try {
+ copyAndVerify(source, target);
+ throw new RuntimeException("FileAlreadyExistsException expected");
+ } catch (FileAlreadyExistsException x) {
+ }
+ entry.delete();
+ source.delete();
+ target.delete();
+
+ /**
+ * Test: copy regular file + attributes
+ */
+ source = createSourceFile(dir);
+ target = getTargetFile(dir);
+ copyAndVerify(source, target, COPY_ATTRIBUTES);
+ source.delete();
+ target.delete();
+
+
+ // -- directory --
+
+ /*
+ * Test: copy directory, target does not exist
+ */
+ source = createSourceDirectory(dir);
+ target = getTargetFile(dir);
+ copyAndVerify(source, target);
+ source.delete();
+ target.delete();
+
+ /**
+ * Test: copy directory, target exists
+ */
+ source = createSourceDirectory(dir);
+ target = getTargetFile(dir).createFile();
+ try {
+ copyAndVerify(source, target);
+ throw new RuntimeException("FileAlreadyExistsException expected");
+ } catch (FileAlreadyExistsException x) {
+ }
+ target.delete();
+ target.createDirectory();
+ try {
+ copyAndVerify(source, target);
+ throw new RuntimeException("FileAlreadyExistsException expected");
+ } catch (FileAlreadyExistsException x) {
+ }
+ source.delete();
+ target.delete();
+
+ /**
+ * Test: copy directory, target does not exist
+ */
+ source = createSourceDirectory(dir);
+ target = getTargetFile(dir);
+ copyAndVerify(source, target, REPLACE_EXISTING);
+ source.delete();
+ target.delete();
+
+ /**
+ * Test: copy directory, target exists
+ */
+ source = createSourceDirectory(dir);
+ target = getTargetFile(dir).createFile();
+ copyAndVerify(source, target, REPLACE_EXISTING);
+ source.delete();
+ target.delete();
+
+ /**
+ * Test: copy directory, target exists and is empty directory
+ */
+ source = createSourceDirectory(dir);
+ target = getTargetFile(dir).createDirectory();
+ copyAndVerify(source, target, REPLACE_EXISTING);
+ source.delete();
+ target.delete();
+
+ /**
+ * Test: copy directory, target exists and is non-empty directory
+ */
+ source = createSourceDirectory(dir);
+ target = getTargetFile(dir).createDirectory();
+ entry = target.resolve("foo").createFile();
+ try {
+ copyAndVerify(source, target, REPLACE_EXISTING);
+ throw new RuntimeException("FileAlreadyExistsException expected");
+ } catch (FileAlreadyExistsException x) {
+ }
+ entry.delete();
+ source.delete();
+ target.delete();
+
+ /*
+ * Test: copy directory + attributes
+ */
+ source = createSourceDirectory(dir);
+ target = getTargetFile(dir);
+ copyAndVerify(source, target, COPY_ATTRIBUTES);
+ source.delete();
+ target.delete();
+
+ // -- symbolic links --
+
+ /**
+ * Test: Follow link
+ */
+ if (supportsLinks) {
+ source = createSourceFile(dir);
+ link = dir.resolve("link").createSymbolicLink(source);
+ target = getTargetFile(dir);
+ copyAndVerify(link, target);
+ link.delete();
+ source.delete();
+ }
+
+ /**
+ * Test: Copy link (to file)
+ */
+ if (supportsLinks) {
+ source = createSourceFile(dir);
+ link = dir.resolve("link").createSymbolicLink(source);
+ target = getTargetFile(dir);
+ copyAndVerify(link, target, NOFOLLOW_LINKS);
+ link.delete();
+ source.delete();
+ }
+
+ /**
+ * Test: Copy link (to directory)
+ */
+ if (supportsLinks) {
+ source = dir.resolve("mydir").createDirectory();
+ link = dir.resolve("link").createSymbolicLink(source);
+ target = getTargetFile(dir);
+ copyAndVerify(link, target, NOFOLLOW_LINKS);
+ link.delete();
+ source.delete();
+ }
+
+ /**
+ * Test: Copy broken link
+ */
+ if (supportsLinks) {
+ assertTrue(source.notExists());
+ link = dir.resolve("link").createSymbolicLink(source);
+ target = getTargetFile(dir);
+ copyAndVerify(link, target, NOFOLLOW_LINKS);
+ link.delete();
+ }
+
+ /**
+ * Test: Copy link to UNC (Windows only)
+ */
+ if (supportsLinks &&
+ System.getProperty("os.name").startsWith("Windows"))
+ {
+ Path unc = Paths.get("\\\\rialto\\share\\file");
+ link = dir.resolve("link").createSymbolicLink(unc);
+ target = getTargetFile(dir);
+ copyAndVerify(link, target, NOFOLLOW_LINKS);
+ link.delete();
+ }
+
+ // -- misc. tests --
+
+ /**
+ * Test nulls
+ */
+ source = createSourceFile(dir);
+ target = getTargetFile(dir);
+ try {
+ source.copyTo(null);
+ throw new RuntimeException("NullPointerException expected");
+ } catch (NullPointerException x) { }
+ try {
+ source.copyTo(target, (CopyOption[])null);
+ throw new RuntimeException("NullPointerException expected");
+ } catch (NullPointerException x) { }
+ try {
+ CopyOption[] opts = { REPLACE_EXISTING, null };
+ source.copyTo(target, opts);
+ throw new RuntimeException("NullPointerException expected");
+ } catch (NullPointerException x) { }
+ source.delete();
+
+ /**
+ * Test UOE
+ */
+ source = createSourceFile(dir);
+ target = getTargetFile(dir);
+ try {
+ source.copyTo(target, new CopyOption() { });
+ } catch (UnsupportedOperationException x) { }
+ try {
+ source.copyTo(target, REPLACE_EXISTING, new CopyOption() { });
+ } catch (UnsupportedOperationException x) { }
+ source.delete();
+ }
+
+
+ static void assertTrue(boolean value) {
+ if (!value)
+ throw new RuntimeException("Assertion failed");
+ }
+
+ // computes simple hash of the given file
+ static int computeHash(Path file) throws IOException {
+ int h = 0;
+
+ InputStream in = file.newInputStream();
+ try {
+ byte[] buf = new byte[1024];
+ int n;
+ do {
+ n = in.read(buf);
+ for (int i=0; i<n; i++) {
+ h = 31*h + (buf[i] & 0xff);
+ }
+ } while (n > 0);
+ } finally {
+ in.close();
+ }
+ return h;
+ }
+
+ // create file of random size in given directory
+ static Path createSourceFile(Path dir) throws IOException {
+ String name = "source" + Integer.toString(rand.nextInt());
+ Path file = dir.resolve(name).createFile();
+ byte[] bytes = new byte[rand.nextInt(128*1024)];
+ rand.nextBytes(bytes);
+ OutputStream out = file.newOutputStream();
+ try {
+ out.write(bytes);
+ } finally {
+ out.close();
+ }
+ randomizeAttributes(file);
+ return file;
+ }
+
+ // create directory in the given directory
+ static Path createSourceDirectory(Path dir) throws IOException {
+ String name = "sourcedir" + Integer.toString(rand.nextInt());
+ Path subdir = dir.resolve(name).createDirectory();
+ randomizeAttributes(subdir);
+ return subdir;
+ }
+
+ // "randomize" the file attributes of the given file.
+ static void randomizeAttributes(Path file) throws IOException {
+ String os = System.getProperty("os.name");
+ boolean isWindows = os.startsWith("Windows");
+ boolean isUnix = os.equals("SunOS") || os.equals("Linux");
+ boolean isDirectory = Attributes.readBasicFileAttributes(file, NOFOLLOW_LINKS)
+ .isDirectory();
+
+ if (isUnix) {
+ Set<PosixFilePermission> perms = Attributes
+ .readPosixFileAttributes(file, NOFOLLOW_LINKS).permissions();
+ PosixFilePermission[] toChange = {
+ PosixFilePermission.GROUP_READ,
+ PosixFilePermission.GROUP_WRITE,
+ PosixFilePermission.GROUP_EXECUTE,
+ PosixFilePermission.OTHERS_READ,
+ PosixFilePermission.OTHERS_WRITE,
+ PosixFilePermission.OTHERS_EXECUTE
+ };
+ for (PosixFilePermission perm: toChange) {
+ if (heads()) {
+ perms.add(perm);
+ } else {
+ perms.remove(perm);
+ }
+ }
+ Attributes.setPosixFilePermissions(file, perms);
+ }
+
+ if (isWindows) {
+ DosFileAttributeView view = file
+ .getFileAttributeView(DosFileAttributeView.class, NOFOLLOW_LINKS);
+ // only set or unset the hidden attribute
+ view.setHidden(heads());
+ }
+
+ boolean addUserDefinedFileAttributes = heads() &&
+ file.getFileStore().supportsFileAttributeView("xattr");
+
+ // remove this when copying a direcory copies its named streams
+ if (isWindows && isDirectory) addUserDefinedFileAttributes = false;
+
+ if (addUserDefinedFileAttributes) {
+ UserDefinedFileAttributeView view = file
+ .getFileAttributeView(UserDefinedFileAttributeView.class);
+ int n = rand.nextInt(16);
+ while (n > 0) {
+ byte[] value = new byte[1 + rand.nextInt(100)];
+ view.write("user." + Integer.toString(n), ByteBuffer.wrap(value));
+ n--;
+ }
+ }
+ }
+
+ // create name for file in given directory
+ static Path getTargetFile(Path dir) throws IOException {
+ String name = "target" + Integer.toString(rand.nextInt());
+ return dir.resolve(name);
+ }
+ }