893N/A/*
3909N/A * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
893N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
893N/A *
893N/A * This code is free software; you can redistribute it and/or modify it
893N/A * under the terms of the GNU General Public License version 2 only, as
893N/A * published by the Free Software Foundation.
893N/A *
893N/A * This code is distributed in the hope that it will be useful, but WITHOUT
893N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
893N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
893N/A * version 2 for more details (a copy is included in the LICENSE file that
893N/A * accompanied this code).
893N/A *
893N/A * You should have received a copy of the GNU General Public License version
893N/A * 2 along with this work; if not, write to the Free Software Foundation,
893N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
893N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
893N/A */
893N/A
893N/A/* @test
3471N/A * @bug 4313887 6838333 6917021 7006126
3471N/A * @summary Unit test for java.nio.file.Files copy and move methods
893N/A * @library ..
2094N/A * @build CopyAndMove PassThroughFileSystem
1868N/A * @run main/othervm CopyAndMove
893N/A */
893N/A
893N/Aimport java.nio.ByteBuffer;
893N/Aimport java.nio.file.*;
3471N/Aimport static java.nio.file.Files.*;
893N/Aimport static java.nio.file.StandardCopyOption.*;
893N/Aimport static java.nio.file.LinkOption.*;
893N/Aimport java.nio.file.attribute.*;
893N/Aimport java.io.*;
893N/Aimport java.util.*;
893N/A
893N/Apublic class CopyAndMove {
893N/A static final Random rand = new Random();
893N/A static boolean heads() { return rand.nextBoolean(); }
893N/A
893N/A public static void main(String[] args) throws Exception {
893N/A Path dir1 = TestUtil.createTemporaryDirectory();
893N/A try {
3471N/A
2094N/A // Same directory
3471N/A testCopyFileToFile(dir1, dir1, TestUtil.supportsLinks(dir1));
3471N/A testMove(dir1, dir1, TestUtil.supportsLinks(dir1));
893N/A
2094N/A // Different directories. Use test.dir if possible as it might be
2094N/A // a different volume/file system and so improve test coverage.
2094N/A String testDir = System.getProperty("test.dir", ".");
2094N/A Path dir2 = TestUtil.createTemporaryDirectory(testDir);
2094N/A try {
2094N/A boolean testSymbolicLinks =
2094N/A TestUtil.supportsLinks(dir1) && TestUtil.supportsLinks(dir2);
3471N/A testCopyFileToFile(dir1, dir2, testSymbolicLinks);
3471N/A testMove(dir1, dir2, testSymbolicLinks);
2094N/A } finally {
2094N/A TestUtil.removeAll(dir2);
2094N/A }
2094N/A
2094N/A // Target is location associated with custom provider
2094N/A Path dir3 = PassThroughFileSystem.create().getPath(dir1.toString());
3471N/A testCopyFileToFile(dir1, dir3, false);
3471N/A testMove(dir1, dir3, false);
3471N/A
3471N/A // Test copy(InputStream,Path) and copy(Path,OutputStream)
3471N/A testCopyInputStreamToFile();
3471N/A testCopyFileToOuputStream();
893N/A
893N/A } finally {
893N/A TestUtil.removeAll(dir1);
893N/A }
893N/A }
893N/A
893N/A static void checkBasicAttributes(BasicFileAttributes attrs1,
893N/A BasicFileAttributes attrs2)
893N/A {
893N/A // check file type
893N/A assertTrue(attrs1.isRegularFile() == attrs2.isRegularFile());
893N/A assertTrue(attrs1.isDirectory() == attrs2.isDirectory());
893N/A assertTrue(attrs1.isSymbolicLink() == attrs2.isSymbolicLink());
893N/A assertTrue(attrs1.isOther() == attrs2.isOther());
893N/A
1319N/A // check last modified time
1319N/A long time1 = attrs1.lastModifiedTime().toMillis();
1319N/A long time2 = attrs2.lastModifiedTime().toMillis();
893N/A assertTrue(time1 == time2);
893N/A
893N/A // check size
893N/A if (attrs1.isRegularFile())
893N/A assertTrue(attrs1.size() == attrs2.size());
893N/A }
893N/A
893N/A static void checkPosixAttributes(PosixFileAttributes attrs1,
893N/A PosixFileAttributes attrs2)
893N/A {
893N/A assertTrue(attrs1.permissions().equals(attrs2.permissions()));
893N/A assertTrue(attrs1.owner().equals(attrs2.owner()));
893N/A assertTrue(attrs1.group().equals(attrs2.group()));
893N/A }
893N/A
893N/A static void checkDosAttributes(DosFileAttributes attrs1,
893N/A DosFileAttributes attrs2)
893N/A {
893N/A assertTrue(attrs1.isReadOnly() == attrs2.isReadOnly());
893N/A assertTrue(attrs1.isHidden() == attrs2.isHidden());
893N/A assertTrue(attrs1.isSystem() == attrs2.isSystem());
893N/A }
893N/A
893N/A static void checkUserDefinedFileAttributes(Map<String,ByteBuffer> attrs1,
893N/A Map<String,ByteBuffer> attrs2)
893N/A {
893N/A assert attrs1.size() == attrs2.size();
893N/A for (String name: attrs1.keySet()) {
893N/A ByteBuffer bb1 = attrs1.get(name);
893N/A ByteBuffer bb2 = attrs2.get(name);
893N/A assertTrue(bb2 != null);
893N/A assertTrue(bb1.equals(bb2));
893N/A }
893N/A }
893N/A
893N/A static Map<String,ByteBuffer> readUserDefinedFileAttributes(Path file)
893N/A throws IOException
893N/A {
3471N/A UserDefinedFileAttributeView view =
3471N/A getFileAttributeView(file, UserDefinedFileAttributeView.class);
3471N/A Map<String,ByteBuffer> result = new HashMap<>();
893N/A for (String name: view.list()) {
893N/A int size = view.size(name);
893N/A ByteBuffer bb = ByteBuffer.allocate(size);
893N/A int n = view.read(name, bb);
893N/A assertTrue(n == size);
893N/A bb.flip();
893N/A result.put(name, bb);
893N/A }
893N/A return result;
893N/A }
893N/A
893N/A // move source to target with verification
893N/A static void moveAndVerify(Path source, Path target, CopyOption... options)
893N/A throws IOException
893N/A {
893N/A // read attributes before file is moved
893N/A BasicFileAttributes basicAttributes = null;
893N/A PosixFileAttributes posixAttributes = null;
893N/A DosFileAttributes dosAttributes = null;
893N/A Map<String,ByteBuffer> namedAttributes = null;
893N/A
893N/A // get file attributes of source file
893N/A String os = System.getProperty("os.name");
893N/A if (os.startsWith("Windows")) {
3471N/A dosAttributes = readAttributes(source, DosFileAttributes.class, NOFOLLOW_LINKS);
893N/A basicAttributes = dosAttributes;
4652N/A } else {
4652N/A posixAttributes = readAttributes(source, PosixFileAttributes.class, NOFOLLOW_LINKS);
4652N/A basicAttributes = posixAttributes;
893N/A }
893N/A if (basicAttributes == null)
3471N/A basicAttributes = readAttributes(source, BasicFileAttributes.class, NOFOLLOW_LINKS);
893N/A
893N/A // hash file contents if regular file
893N/A int hash = (basicAttributes.isRegularFile()) ? computeHash(source) : 0;
893N/A
893N/A // record link target if symbolic link
893N/A Path linkTarget = null;
893N/A if (basicAttributes.isSymbolicLink())
3471N/A linkTarget = readSymbolicLink(source);
893N/A
893N/A // read named attributes if available (and file is not a sym link)
893N/A if (!basicAttributes.isSymbolicLink() &&
3471N/A getFileStore(source).supportsFileAttributeView("xattr"))
893N/A {
893N/A namedAttributes = readUserDefinedFileAttributes(source);
893N/A }
893N/A
893N/A // move file
3471N/A Path result = move(source, target, options);
3471N/A assertTrue(result == target);
893N/A
893N/A // verify source does not exist
3471N/A assertTrue(notExists(source));
893N/A
893N/A // verify file contents
893N/A if (basicAttributes.isRegularFile()) {
893N/A if (computeHash(target) != hash)
893N/A throw new RuntimeException("Failed to verify move of regular file");
893N/A }
893N/A
893N/A // verify link target
893N/A if (basicAttributes.isSymbolicLink()) {
3471N/A if (!readSymbolicLink(target).equals(linkTarget))
893N/A throw new RuntimeException("Failed to verify move of symbolic link");
893N/A }
893N/A
893N/A // verify basic attributes
893N/A checkBasicAttributes(basicAttributes,
3471N/A readAttributes(target, BasicFileAttributes.class, NOFOLLOW_LINKS));
893N/A
2094N/A // verify other attributes when same provider
2094N/A if (source.getFileSystem().provider() == target.getFileSystem().provider()) {
2094N/A
2094N/A // verify POSIX attributes
2094N/A if (posixAttributes != null && !basicAttributes.isSymbolicLink()) {
2094N/A checkPosixAttributes(posixAttributes,
3471N/A readAttributes(target, PosixFileAttributes.class, NOFOLLOW_LINKS));
2094N/A }
893N/A
2094N/A // verify DOS attributes
2094N/A if (dosAttributes != null && !basicAttributes.isSymbolicLink()) {
3471N/A DosFileAttributes attrs =
3471N/A readAttributes(target, DosFileAttributes.class, NOFOLLOW_LINKS);
3471N/A checkDosAttributes(dosAttributes, attrs);
2094N/A }
893N/A
2094N/A // verify named attributes
2094N/A if (namedAttributes != null &&
3471N/A getFileStore(target).supportsFileAttributeView("xattr"))
2094N/A {
2094N/A checkUserDefinedFileAttributes(namedAttributes,
2094N/A readUserDefinedFileAttributes(target));
2094N/A }
893N/A }
893N/A }
893N/A
893N/A /**
3471N/A * Tests all possible ways to invoke move
893N/A */
3471N/A static void testMove(Path dir1, Path dir2, boolean supportsLinks)
2094N/A throws IOException
2094N/A {
893N/A Path source, target, entry;
893N/A
3471N/A boolean sameDevice = getFileStore(dir1).equals(getFileStore(dir2));
893N/A
893N/A // -- regular file --
893N/A
893N/A /**
893N/A * Test: move regular file, target does not exist
893N/A */
893N/A source = createSourceFile(dir1);
2094N/A target = getTargetFile(dir2);
893N/A moveAndVerify(source, target);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: move regular file, target exists
893N/A */
893N/A source = createSourceFile(dir1);
3471N/A target = getTargetFile(dir2);
3471N/A createFile(target);
893N/A try {
893N/A moveAndVerify(source, target);
893N/A throw new RuntimeException("FileAlreadyExistsException expected");
893N/A } catch (FileAlreadyExistsException x) {
893N/A }
3471N/A delete(target);
3471N/A createDirectory(target);
893N/A try {
893N/A moveAndVerify(source, target);
893N/A throw new RuntimeException("FileAlreadyExistsException expected");
893N/A } catch (FileAlreadyExistsException x) {
893N/A }
3471N/A delete(source);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: move regular file, target does not exist
893N/A */
893N/A source = createSourceFile(dir1);
2094N/A target = getTargetFile(dir2);
893N/A moveAndVerify(source, target, REPLACE_EXISTING);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: move regular file, target exists
893N/A */
893N/A source = createSourceFile(dir1);
3471N/A target = getTargetFile(dir2);
3471N/A createFile(target);
893N/A moveAndVerify(source, target, REPLACE_EXISTING);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: move regular file, target exists and is empty directory
893N/A */
893N/A source = createSourceFile(dir1);
3471N/A target = getTargetFile(dir2);
3471N/A createDirectory(target);
893N/A moveAndVerify(source, target, REPLACE_EXISTING);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: move regular file, target exists and is non-empty directory
893N/A */
893N/A source = createSourceFile(dir1);
3471N/A target = getTargetFile(dir2);
3471N/A createDirectory(target);
3471N/A entry = target.resolve("foo");
3471N/A createFile(entry);
893N/A try {
893N/A moveAndVerify(source, target);
893N/A throw new RuntimeException("FileAlreadyExistsException expected");
893N/A } catch (FileAlreadyExistsException x) {
893N/A }
3471N/A delete(entry);
3471N/A delete(source);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test atomic move of regular file (same file store)
893N/A */
893N/A source = createSourceFile(dir1);
893N/A target = getTargetFile(dir1);
893N/A moveAndVerify(source, target, ATOMIC_MOVE);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test atomic move of regular file (different file store)
893N/A */
893N/A if (!sameDevice) {
893N/A source = createSourceFile(dir1);
893N/A target = getTargetFile(dir2);
893N/A try {
893N/A moveAndVerify(source, target, ATOMIC_MOVE);
893N/A throw new RuntimeException("AtomicMoveNotSupportedException expected");
893N/A } catch (AtomicMoveNotSupportedException x) {
893N/A }
3471N/A delete(source);
893N/A }
893N/A
893N/A // -- directories --
893N/A
893N/A /*
893N/A * Test: move empty directory, target does not exist
893N/A */
893N/A source = createSourceDirectory(dir1);
2094N/A target = getTargetFile(dir2);
893N/A moveAndVerify(source, target);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: move empty directory, target exists
893N/A */
893N/A source = createSourceDirectory(dir1);
3471N/A target = getTargetFile(dir2);
3471N/A createFile(target);
893N/A try {
893N/A moveAndVerify(source, target);
893N/A throw new RuntimeException("FileAlreadyExistsException expected");
893N/A } catch (FileAlreadyExistsException x) {
893N/A }
3471N/A delete(target);
3471N/A createDirectory(target);
893N/A try {
893N/A moveAndVerify(source, target);
893N/A throw new RuntimeException("FileAlreadyExistsException expected");
893N/A } catch (FileAlreadyExistsException x) {
893N/A }
3471N/A delete(source);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: move empty directory, target does not exist
893N/A */
893N/A source = createSourceDirectory(dir1);
2094N/A target = getTargetFile(dir2);
893N/A moveAndVerify(source, target, REPLACE_EXISTING);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: move empty directory, target exists
893N/A */
893N/A source = createSourceDirectory(dir1);
3471N/A target = getTargetFile(dir2);
3471N/A createFile(target);
893N/A moveAndVerify(source, target, REPLACE_EXISTING);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: move empty, target exists and is empty directory
893N/A */
893N/A source = createSourceDirectory(dir1);
3471N/A target = getTargetFile(dir2);
3471N/A createDirectory(target);
893N/A moveAndVerify(source, target, REPLACE_EXISTING);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: move empty directory, target exists and is non-empty directory
893N/A */
893N/A source = createSourceDirectory(dir1);
3471N/A target = getTargetFile(dir2);
3471N/A createDirectory(target);
3471N/A entry = target.resolve("foo");
3471N/A createFile(entry);
893N/A try {
893N/A moveAndVerify(source, target, REPLACE_EXISTING);
3471N/A throw new RuntimeException("DirectoryNotEmptyException expected");
3471N/A } catch (DirectoryNotEmptyException x) {
893N/A }
3471N/A delete(entry);
3471N/A delete(source);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: move non-empty directory (same file system)
893N/A */
893N/A source = createSourceDirectory(dir1);
3471N/A createFile(source.resolve("foo"));
893N/A target = getTargetFile(dir1);
893N/A moveAndVerify(source, target);
3471N/A delete(target.resolve("foo"));
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: move non-empty directory (different file store)
893N/A */
893N/A if (!sameDevice) {
893N/A source = createSourceDirectory(dir1);
3471N/A createFile(source.resolve("foo"));
893N/A target = getTargetFile(dir2);
893N/A try {
893N/A moveAndVerify(source, target);
893N/A throw new RuntimeException("IOException expected");
893N/A } catch (IOException x) {
893N/A }
3471N/A delete(source.resolve("foo"));
3471N/A delete(source);
893N/A }
893N/A
893N/A /**
893N/A * Test atomic move of directory (same file store)
893N/A */
893N/A source = createSourceDirectory(dir1);
3471N/A createFile(source.resolve("foo"));
893N/A target = getTargetFile(dir1);
893N/A moveAndVerify(source, target, ATOMIC_MOVE);
3471N/A delete(target.resolve("foo"));
3471N/A delete(target);
893N/A
893N/A // -- symbolic links --
893N/A
893N/A /**
893N/A * Test: Move symbolic link to file, target does not exist
893N/A */
893N/A if (supportsLinks) {
893N/A Path tmp = createSourceFile(dir1);
3471N/A source = dir1.resolve("link");
3471N/A createSymbolicLink(source, tmp);
2094N/A target = getTargetFile(dir2);
893N/A moveAndVerify(source, target);
3471N/A delete(target);
3471N/A delete(tmp);
893N/A }
893N/A
893N/A /**
893N/A * Test: Move symbolic link to directory, target does not exist
893N/A */
893N/A if (supportsLinks) {
3471N/A source = dir1.resolve("link");
3471N/A createSymbolicLink(source, dir2);
2094N/A target = getTargetFile(dir2);
893N/A moveAndVerify(source, target);
3471N/A delete(target);
893N/A }
893N/A
893N/A /**
893N/A * Test: Move broken symbolic link, target does not exists
893N/A */
893N/A if (supportsLinks) {
893N/A Path tmp = Paths.get("doesnotexist");
3471N/A source = dir1.resolve("link");
3471N/A createSymbolicLink(source, tmp);
2094N/A target = getTargetFile(dir2);
893N/A moveAndVerify(source, target);
3471N/A delete(target);
893N/A }
893N/A
893N/A /**
893N/A * Test: Move symbolic link, target exists
893N/A */
893N/A if (supportsLinks) {
3471N/A source = dir1.resolve("link");
3471N/A createSymbolicLink(source, dir2);
3471N/A target = getTargetFile(dir2);
3471N/A createFile(target);
893N/A try {
893N/A moveAndVerify(source, target);
893N/A throw new RuntimeException("FileAlreadyExistsException expected");
893N/A } catch (FileAlreadyExistsException x) {
893N/A }
3471N/A delete(source);
3471N/A delete(target);
893N/A }
893N/A
893N/A /**
893N/A * Test: Move regular file, target exists
893N/A */
893N/A if (supportsLinks) {
3471N/A source = dir1.resolve("link");
3471N/A createSymbolicLink(source, dir2);
3471N/A target = getTargetFile(dir2);
3471N/A createFile(target);
893N/A moveAndVerify(source, target, REPLACE_EXISTING);
3471N/A delete(target);
893N/A }
893N/A
893N/A /**
893N/A * Test: move symbolic link, target exists and is empty directory
893N/A */
893N/A if (supportsLinks) {
3471N/A source = dir1.resolve("link");
3471N/A createSymbolicLink(source, dir2);
3471N/A target = getTargetFile(dir2);
3471N/A createDirectory(target);
893N/A moveAndVerify(source, target, REPLACE_EXISTING);
3471N/A delete(target);
893N/A }
893N/A
893N/A /**
893N/A * Test: symbolic link, target exists and is non-empty directory
893N/A */
893N/A if (supportsLinks) {
3471N/A source = dir1.resolve("link");
3471N/A createSymbolicLink(source, dir2);
3471N/A target = getTargetFile(dir2);
3471N/A createDirectory(target);
3471N/A entry = target.resolve("foo");
3471N/A createFile(entry);
893N/A try {
893N/A moveAndVerify(source, target);
893N/A throw new RuntimeException("FileAlreadyExistsException expected");
893N/A } catch (FileAlreadyExistsException x) {
893N/A }
3471N/A delete(entry);
3471N/A delete(source);
3471N/A delete(target);
893N/A }
893N/A
893N/A /**
893N/A * Test atomic move of symbolic link (same file store)
893N/A */
893N/A if (supportsLinks) {
3471N/A source = dir1.resolve("link");
3471N/A createSymbolicLink(source, dir1);
3471N/A target = getTargetFile(dir2);
3471N/A createFile(target);
893N/A moveAndVerify(source, target, REPLACE_EXISTING);
3471N/A delete(target);
893N/A }
893N/A
893N/A // -- misc. tests --
893N/A
893N/A /**
893N/A * Test nulls
893N/A */
893N/A source = createSourceFile(dir1);
2094N/A target = getTargetFile(dir2);
893N/A try {
3471N/A move(null, target);
893N/A throw new RuntimeException("NullPointerException expected");
893N/A } catch (NullPointerException x) { }
893N/A try {
3471N/A move(source, null);
3471N/A throw new RuntimeException("NullPointerException expected");
3471N/A } catch (NullPointerException x) { }
3471N/A try {
3471N/A move(source, target, (CopyOption[])null);
893N/A throw new RuntimeException("NullPointerException expected");
893N/A } catch (NullPointerException x) { }
893N/A try {
893N/A CopyOption[] opts = { REPLACE_EXISTING, null };
3471N/A move(source, target, opts);
893N/A throw new RuntimeException("NullPointerException expected");
893N/A } catch (NullPointerException x) { }
3471N/A delete(source);
893N/A
893N/A /**
893N/A * Test UOE
893N/A */
893N/A source = createSourceFile(dir1);
2094N/A target = getTargetFile(dir2);
893N/A try {
3471N/A move(source, target, new CopyOption() { });
893N/A } catch (UnsupportedOperationException x) { }
893N/A try {
3471N/A move(source, target, REPLACE_EXISTING, new CopyOption() { });
893N/A } catch (UnsupportedOperationException x) { }
3471N/A delete(source);
893N/A }
893N/A
893N/A // copy source to target with verification
893N/A static void copyAndVerify(Path source, Path target, CopyOption... options)
893N/A throws IOException
893N/A {
3471N/A Path result = copy(source, target, options);
3471N/A assertTrue(result == target);
893N/A
893N/A // get attributes of source and target file to verify copy
893N/A boolean followLinks = true;
893N/A LinkOption[] linkOptions = new LinkOption[0];
893N/A boolean copyAttributes = false;
893N/A for (CopyOption opt : options) {
893N/A if (opt == NOFOLLOW_LINKS) {
893N/A followLinks = false;
893N/A linkOptions = new LinkOption[] { NOFOLLOW_LINKS };
893N/A }
893N/A if (opt == COPY_ATTRIBUTES)
893N/A copyAttributes = true;
893N/A }
3471N/A BasicFileAttributes basicAttributes =
3471N/A readAttributes(source, BasicFileAttributes.class, linkOptions);
893N/A
893N/A // check hash if regular file
893N/A if (basicAttributes.isRegularFile())
893N/A assertTrue(computeHash(source) == computeHash(target));
893N/A
893N/A // check link target if symbolic link
893N/A if (basicAttributes.isSymbolicLink())
3471N/A assert(readSymbolicLink(source).equals(readSymbolicLink(target)));
893N/A
893N/A // check that attributes are copied
893N/A if (copyAttributes && followLinks) {
893N/A checkBasicAttributes(basicAttributes,
3471N/A readAttributes(source, BasicFileAttributes.class, linkOptions));
893N/A
2094N/A // verify other attributes when same provider
2094N/A if (source.getFileSystem().provider() == target.getFileSystem().provider()) {
2094N/A
2094N/A // check POSIX attributes are copied
2094N/A String os = System.getProperty("os.name");
2094N/A if (os.equals("SunOS") || os.equals("Linux")) {
2094N/A checkPosixAttributes(
3471N/A readAttributes(source, PosixFileAttributes.class, linkOptions),
3471N/A readAttributes(target, PosixFileAttributes.class, linkOptions));
2094N/A }
893N/A
2094N/A // check DOS attributes are copied
2094N/A if (os.startsWith("Windows")) {
2094N/A checkDosAttributes(
3471N/A readAttributes(source, DosFileAttributes.class, linkOptions),
3471N/A readAttributes(target, DosFileAttributes.class, linkOptions));
2094N/A }
893N/A
2094N/A // check named attributes are copied
2094N/A if (followLinks &&
3471N/A getFileStore(source).supportsFileAttributeView("xattr") &&
3471N/A getFileStore(target).supportsFileAttributeView("xattr"))
2094N/A {
2094N/A checkUserDefinedFileAttributes(readUserDefinedFileAttributes(source),
2094N/A readUserDefinedFileAttributes(target));
2094N/A }
893N/A }
893N/A }
893N/A }
893N/A
893N/A /**
3471N/A * Tests all possible ways to invoke copy to copy a file to a file
893N/A */
3471N/A static void testCopyFileToFile(Path dir1, Path dir2, boolean supportsLinks)
2094N/A throws IOException
2094N/A {
893N/A Path source, target, link, entry;
893N/A
893N/A // -- regular file --
893N/A
893N/A /**
893N/A * Test: move regular file, target does not exist
893N/A */
2094N/A source = createSourceFile(dir1);
2094N/A target = getTargetFile(dir2);
893N/A copyAndVerify(source, target);
3471N/A delete(source);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: copy regular file, target exists
893N/A */
2094N/A source = createSourceFile(dir1);
3471N/A target = getTargetFile(dir2);
3471N/A createFile(target);
893N/A try {
893N/A copyAndVerify(source, target);
893N/A throw new RuntimeException("FileAlreadyExistsException expected");
893N/A } catch (FileAlreadyExistsException x) {
893N/A }
3471N/A delete(target);
3471N/A createDirectory(target);
893N/A try {
893N/A copyAndVerify(source, target);
893N/A throw new RuntimeException("FileAlreadyExistsException expected");
893N/A } catch (FileAlreadyExistsException x) {
893N/A }
3471N/A delete(source);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: copy regular file, target does not exist
893N/A */
2094N/A source = createSourceFile(dir1);
2094N/A target = getTargetFile(dir2);
893N/A copyAndVerify(source, target, REPLACE_EXISTING);
3471N/A delete(source);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: copy regular file, target exists
893N/A */
2094N/A source = createSourceFile(dir1);
3471N/A target = getTargetFile(dir2);
3471N/A createFile(target);
893N/A copyAndVerify(source, target, REPLACE_EXISTING);
3471N/A delete(source);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: copy regular file, target exists and is empty directory
893N/A */
2094N/A source = createSourceFile(dir1);
3471N/A target = getTargetFile(dir2);
3471N/A createDirectory(target);
893N/A copyAndVerify(source, target, REPLACE_EXISTING);
3471N/A delete(source);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: copy regular file, target exists and is non-empty directory
893N/A */
2094N/A source = createSourceFile(dir1);
3471N/A target = getTargetFile(dir2);
3471N/A createDirectory(target);
3471N/A entry = target.resolve("foo");
3471N/A createFile(entry);
893N/A try {
893N/A copyAndVerify(source, target);
893N/A throw new RuntimeException("FileAlreadyExistsException expected");
893N/A } catch (FileAlreadyExistsException x) {
893N/A }
3471N/A delete(entry);
3471N/A delete(source);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: copy regular file + attributes
893N/A */
2094N/A source = createSourceFile(dir1);
2094N/A target = getTargetFile(dir2);
893N/A copyAndVerify(source, target, COPY_ATTRIBUTES);
3471N/A delete(source);
3471N/A delete(target);
893N/A
893N/A
893N/A // -- directory --
893N/A
893N/A /*
893N/A * Test: copy directory, target does not exist
893N/A */
2094N/A source = createSourceDirectory(dir1);
2094N/A target = getTargetFile(dir2);
893N/A copyAndVerify(source, target);
3471N/A delete(source);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: copy directory, target exists
893N/A */
2094N/A source = createSourceDirectory(dir1);
3471N/A target = getTargetFile(dir2);
3471N/A createFile(target);
893N/A try {
893N/A copyAndVerify(source, target);
893N/A throw new RuntimeException("FileAlreadyExistsException expected");
893N/A } catch (FileAlreadyExistsException x) {
893N/A }
3471N/A delete(target);
3471N/A createDirectory(target);
893N/A try {
893N/A copyAndVerify(source, target);
893N/A throw new RuntimeException("FileAlreadyExistsException expected");
893N/A } catch (FileAlreadyExistsException x) {
893N/A }
3471N/A delete(source);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: copy directory, target does not exist
893N/A */
2094N/A source = createSourceDirectory(dir1);
2094N/A target = getTargetFile(dir2);
893N/A copyAndVerify(source, target, REPLACE_EXISTING);
3471N/A delete(source);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: copy directory, target exists
893N/A */
2094N/A source = createSourceDirectory(dir1);
3471N/A target = getTargetFile(dir2);
3471N/A createFile(target);
893N/A copyAndVerify(source, target, REPLACE_EXISTING);
3471N/A delete(source);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: copy directory, target exists and is empty directory
893N/A */
2094N/A source = createSourceDirectory(dir1);
3471N/A target = getTargetFile(dir2);
3471N/A createDirectory(target);
893N/A copyAndVerify(source, target, REPLACE_EXISTING);
3471N/A delete(source);
3471N/A delete(target);
893N/A
893N/A /**
893N/A * Test: copy directory, target exists and is non-empty directory
893N/A */
2094N/A source = createSourceDirectory(dir1);
3471N/A target = getTargetFile(dir2);
3471N/A createDirectory(target);
3471N/A entry = target.resolve("foo");
3471N/A createFile(entry);
893N/A try {
893N/A copyAndVerify(source, target, REPLACE_EXISTING);
3471N/A throw new RuntimeException("DirectoryNotEmptyException expected");
3471N/A } catch (DirectoryNotEmptyException x) {
893N/A }
3471N/A delete(entry);
3471N/A delete(source);
3471N/A delete(target);
893N/A
893N/A /*
893N/A * Test: copy directory + attributes
893N/A */
2094N/A source = createSourceDirectory(dir1);
2094N/A target = getTargetFile(dir2);
893N/A copyAndVerify(source, target, COPY_ATTRIBUTES);
3471N/A delete(source);
3471N/A delete(target);
893N/A
893N/A // -- symbolic links --
893N/A
893N/A /**
893N/A * Test: Follow link
893N/A */
893N/A if (supportsLinks) {
2094N/A source = createSourceFile(dir1);
3471N/A link = dir1.resolve("link");
3471N/A createSymbolicLink(link, source);
2094N/A target = getTargetFile(dir2);
893N/A copyAndVerify(link, target);
3471N/A delete(link);
3471N/A delete(source);
893N/A }
893N/A
893N/A /**
893N/A * Test: Copy link (to file)
893N/A */
893N/A if (supportsLinks) {
2094N/A source = createSourceFile(dir1);
3471N/A link = dir1.resolve("link");
3471N/A createSymbolicLink(link, source);
2094N/A target = getTargetFile(dir2);
893N/A copyAndVerify(link, target, NOFOLLOW_LINKS);
3471N/A delete(link);
3471N/A delete(source);
893N/A }
893N/A
893N/A /**
893N/A * Test: Copy link (to directory)
893N/A */
893N/A if (supportsLinks) {
3471N/A source = dir1.resolve("mydir");
3471N/A createDirectory(source);
3471N/A link = dir1.resolve("link");
3471N/A createSymbolicLink(link, source);
2094N/A target = getTargetFile(dir2);
893N/A copyAndVerify(link, target, NOFOLLOW_LINKS);
3471N/A delete(link);
3471N/A delete(source);
893N/A }
893N/A
893N/A /**
893N/A * Test: Copy broken link
893N/A */
893N/A if (supportsLinks) {
3471N/A assertTrue(notExists(source));
3471N/A link = dir1.resolve("link");
3471N/A createSymbolicLink(link, source);
2094N/A target = getTargetFile(dir2);
893N/A copyAndVerify(link, target, NOFOLLOW_LINKS);
3471N/A delete(link);
893N/A }
893N/A
893N/A /**
893N/A * Test: Copy link to UNC (Windows only)
893N/A */
893N/A if (supportsLinks &&
893N/A System.getProperty("os.name").startsWith("Windows"))
893N/A {
893N/A Path unc = Paths.get("\\\\rialto\\share\\file");
3471N/A link = dir1.resolve("link");
3471N/A createSymbolicLink(link, unc);
2094N/A target = getTargetFile(dir2);
893N/A copyAndVerify(link, target, NOFOLLOW_LINKS);
3471N/A delete(link);
893N/A }
893N/A
893N/A // -- misc. tests --
893N/A
893N/A /**
893N/A * Test nulls
893N/A */
2094N/A source = createSourceFile(dir1);
2094N/A target = getTargetFile(dir2);
893N/A try {
3471N/A copy(source, null);
893N/A throw new RuntimeException("NullPointerException expected");
893N/A } catch (NullPointerException x) { }
893N/A try {
3471N/A copy(source, target, (CopyOption[])null);
893N/A throw new RuntimeException("NullPointerException expected");
893N/A } catch (NullPointerException x) { }
893N/A try {
893N/A CopyOption[] opts = { REPLACE_EXISTING, null };
3471N/A copy(source, target, opts);
893N/A throw new RuntimeException("NullPointerException expected");
893N/A } catch (NullPointerException x) { }
3471N/A delete(source);
893N/A
893N/A /**
893N/A * Test UOE
893N/A */
2094N/A source = createSourceFile(dir1);
2094N/A target = getTargetFile(dir2);
893N/A try {
3471N/A copy(source, target, new CopyOption() { });
893N/A } catch (UnsupportedOperationException x) { }
893N/A try {
3471N/A copy(source, target, REPLACE_EXISTING, new CopyOption() { });
893N/A } catch (UnsupportedOperationException x) { }
3471N/A delete(source);
3471N/A }
3471N/A
3471N/A /**
3471N/A * Test copy from an input stream to a file
3471N/A */
3471N/A static void testCopyInputStreamToFile() throws IOException {
3471N/A testCopyInputStreamToFile(0);
3471N/A for (int i=0; i<100; i++) {
3471N/A testCopyInputStreamToFile(rand.nextInt(32000));
3471N/A }
3471N/A
3471N/A // FileAlreadyExistsException
3471N/A Path target = createTempFile("blah", null);
3471N/A try {
3471N/A InputStream in = new ByteArrayInputStream(new byte[0]);
3471N/A try {
3471N/A copy(in, target);
3471N/A throw new RuntimeException("FileAlreadyExistsException expected");
3471N/A } catch (FileAlreadyExistsException ignore) { }
3471N/A } finally {
3471N/A delete(target);
3471N/A }
3471N/A Path tmpdir = createTempDirectory("blah");
3471N/A try {
3471N/A if (TestUtil.supportsLinks(tmpdir)) {
3471N/A Path link = createSymbolicLink(tmpdir.resolve("link"),
3471N/A tmpdir.resolve("target"));
3471N/A try {
3471N/A InputStream in = new ByteArrayInputStream(new byte[0]);
3471N/A try {
3471N/A copy(in, link);
3471N/A throw new RuntimeException("FileAlreadyExistsException expected");
3471N/A } catch (FileAlreadyExistsException ignore) { }
3471N/A } finally {
3471N/A delete(link);
3471N/A }
3471N/A }
3471N/A } finally {
3471N/A delete(tmpdir);
3471N/A }
3471N/A
3471N/A
3471N/A // nulls
3471N/A try {
3471N/A copy((InputStream)null, target);
3471N/A throw new RuntimeException("NullPointerException expected");
3471N/A } catch (NullPointerException ignore) { }
3471N/A try {
3471N/A copy(new ByteArrayInputStream(new byte[0]), (Path)null);
3471N/A throw new RuntimeException("NullPointerException expected");
3471N/A } catch (NullPointerException ignore) { }
893N/A }
893N/A
3471N/A static void testCopyInputStreamToFile(int size) throws IOException {
3471N/A Path tmpdir = createTempDirectory("blah");
3471N/A Path source = tmpdir.resolve("source");
3471N/A Path target = tmpdir.resolve("target");
3471N/A try {
3471N/A boolean testReplaceExisting = rand.nextBoolean();
3471N/A
3471N/A // create source file
3471N/A byte[] b = new byte[size];
3471N/A rand.nextBytes(b);
3471N/A write(source, b);
3471N/A
3471N/A // target file might already exist
3471N/A if (testReplaceExisting && rand.nextBoolean()) {
3471N/A write(target, new byte[rand.nextInt(512)]);
3471N/A }
3471N/A
3471N/A // copy from stream to file
3471N/A InputStream in = new FileInputStream(source.toFile());
3471N/A try {
3471N/A long n;
3471N/A if (testReplaceExisting) {
3471N/A n = copy(in, target, StandardCopyOption.REPLACE_EXISTING);
3471N/A } else {
3471N/A n = copy(in, target);
3471N/A }
3471N/A assertTrue(in.read() == -1); // EOF
3471N/A assertTrue(n == size);
3471N/A assertTrue(size(target) == size);
3471N/A } finally {
3471N/A in.close();
3471N/A }
3471N/A
3471N/A // check file
3471N/A byte[] read = readAllBytes(target);
3471N/A assertTrue(Arrays.equals(read, b));
3471N/A
3471N/A } finally {
3471N/A deleteIfExists(source);
3471N/A deleteIfExists(target);
3471N/A delete(tmpdir);
3471N/A }
3471N/A }
3471N/A
3471N/A /**
3471N/A * Test copy from file to output stream
3471N/A */
3471N/A static void testCopyFileToOuputStream() throws IOException {
3471N/A testCopyFileToOuputStream(0);
3471N/A for (int i=0; i<100; i++) {
3471N/A testCopyFileToOuputStream(rand.nextInt(32000));
3471N/A }
3471N/A
3471N/A // nulls
3471N/A try {
3471N/A copy((Path)null, new ByteArrayOutputStream());
3471N/A throw new RuntimeException("NullPointerException expected");
3471N/A } catch (NullPointerException ignore) { }
3471N/A try {
3471N/A Path source = createTempFile("blah", null);
3471N/A delete(source);
3471N/A copy(source, (OutputStream)null);
3471N/A throw new RuntimeException("NullPointerException expected");
3471N/A } catch (NullPointerException ignore) { }
3471N/A }
3471N/A
3471N/A static void testCopyFileToOuputStream(int size) throws IOException {
3471N/A Path source = createTempFile("blah", null);
3471N/A try {
3471N/A byte[] b = new byte[size];
3471N/A rand.nextBytes(b);
3471N/A write(source, b);
3471N/A
3471N/A ByteArrayOutputStream out = new ByteArrayOutputStream();
3471N/A
3471N/A long n = copy(source, out);
3471N/A assertTrue(n == size);
3471N/A assertTrue(out.size() == size);
3471N/A
3471N/A byte[] read = out.toByteArray();
3471N/A assertTrue(Arrays.equals(read, b));
3471N/A
3471N/A // check output stream is open
3471N/A out.write(0);
3471N/A assertTrue(out.size() == size+1);
3471N/A } finally {
3471N/A delete(source);
3471N/A }
3471N/A }
893N/A
893N/A static void assertTrue(boolean value) {
893N/A if (!value)
893N/A throw new RuntimeException("Assertion failed");
893N/A }
893N/A
893N/A // computes simple hash of the given file
893N/A static int computeHash(Path file) throws IOException {
893N/A int h = 0;
893N/A
3471N/A try (InputStream in = newInputStream(file)) {
893N/A byte[] buf = new byte[1024];
893N/A int n;
893N/A do {
893N/A n = in.read(buf);
893N/A for (int i=0; i<n; i++) {
893N/A h = 31*h + (buf[i] & 0xff);
893N/A }
893N/A } while (n > 0);
893N/A }
893N/A return h;
893N/A }
893N/A
893N/A // create file of random size in given directory
893N/A static Path createSourceFile(Path dir) throws IOException {
893N/A String name = "source" + Integer.toString(rand.nextInt());
3471N/A Path file = dir.resolve(name);
3471N/A createFile(file);
893N/A byte[] bytes = new byte[rand.nextInt(128*1024)];
893N/A rand.nextBytes(bytes);
3471N/A try (OutputStream out = newOutputStream(file)) {
893N/A out.write(bytes);
893N/A }
893N/A randomizeAttributes(file);
893N/A return file;
893N/A }
893N/A
893N/A // create directory in the given directory
893N/A static Path createSourceDirectory(Path dir) throws IOException {
893N/A String name = "sourcedir" + Integer.toString(rand.nextInt());
3471N/A Path subdir = dir.resolve(name);
3471N/A createDirectory(subdir);
893N/A randomizeAttributes(subdir);
893N/A return subdir;
893N/A }
893N/A
893N/A // "randomize" the file attributes of the given file.
893N/A static void randomizeAttributes(Path file) throws IOException {
893N/A String os = System.getProperty("os.name");
893N/A boolean isWindows = os.startsWith("Windows");
893N/A boolean isUnix = os.equals("SunOS") || os.equals("Linux");
3471N/A boolean isDirectory = isDirectory(file, NOFOLLOW_LINKS);
893N/A
893N/A if (isUnix) {
3471N/A Set<PosixFilePermission> perms =
3471N/A getPosixFilePermissions(file, NOFOLLOW_LINKS);
893N/A PosixFilePermission[] toChange = {
893N/A PosixFilePermission.GROUP_READ,
893N/A PosixFilePermission.GROUP_WRITE,
893N/A PosixFilePermission.GROUP_EXECUTE,
893N/A PosixFilePermission.OTHERS_READ,
893N/A PosixFilePermission.OTHERS_WRITE,
893N/A PosixFilePermission.OTHERS_EXECUTE
893N/A };
893N/A for (PosixFilePermission perm: toChange) {
893N/A if (heads()) {
893N/A perms.add(perm);
893N/A } else {
893N/A perms.remove(perm);
893N/A }
893N/A }
3471N/A setPosixFilePermissions(file, perms);
893N/A }
893N/A
893N/A if (isWindows) {
3471N/A DosFileAttributeView view =
3471N/A getFileAttributeView(file, DosFileAttributeView.class, NOFOLLOW_LINKS);
893N/A // only set or unset the hidden attribute
893N/A view.setHidden(heads());
893N/A }
893N/A
893N/A boolean addUserDefinedFileAttributes = heads() &&
3471N/A getFileStore(file).supportsFileAttributeView("xattr");
893N/A
893N/A // remove this when copying a direcory copies its named streams
893N/A if (isWindows && isDirectory) addUserDefinedFileAttributes = false;
893N/A
893N/A if (addUserDefinedFileAttributes) {
3471N/A UserDefinedFileAttributeView view =
3471N/A getFileAttributeView(file, UserDefinedFileAttributeView.class);
893N/A int n = rand.nextInt(16);
893N/A while (n > 0) {
893N/A byte[] value = new byte[1 + rand.nextInt(100)];
893N/A view.write("user." + Integer.toString(n), ByteBuffer.wrap(value));
893N/A n--;
893N/A }
893N/A }
893N/A }
893N/A
893N/A // create name for file in given directory
893N/A static Path getTargetFile(Path dir) throws IOException {
893N/A String name = "target" + Integer.toString(rand.nextInt());
893N/A return dir.resolve(name);
893N/A }
893N/A }