| /* |
| * Copyright (c) 2008, 2009, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| /* @test |
| * @bug 4313887 6838333 6917021 |
| * @summary Unit test for java.nio.file.Path copyTo/moveTo methods |
| * @library .. |
| * @build CopyAndMove PassThroughFileSystem |
| * @run main/othervm CopyAndMove |
| */ |
| |
| 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(); } |
| |
| public static void main(String[] args) throws Exception { |
| Path dir1 = TestUtil.createTemporaryDirectory(); |
| try { |
| // Same directory |
| doCopyTests(dir1, dir1, TestUtil.supportsLinks(dir1)); |
| doMoveTests(dir1, dir1, TestUtil.supportsLinks(dir1)); |
| |
| // Different directories. Use test.dir if possible as it might be |
| // a different volume/file system and so improve test coverage. |
| String testDir = System.getProperty("test.dir", "."); |
| Path dir2 = TestUtil.createTemporaryDirectory(testDir); |
| try { |
| boolean testSymbolicLinks = |
| TestUtil.supportsLinks(dir1) && TestUtil.supportsLinks(dir2); |
| doCopyTests(dir1, dir2, testSymbolicLinks); |
| doMoveTests(dir1, dir2, testSymbolicLinks); |
| } finally { |
| TestUtil.removeAll(dir2); |
| } |
| |
| // Target is location associated with custom provider |
| Path dir3 = PassThroughFileSystem.create().getPath(dir1.toString()); |
| doCopyTests(dir1, dir3, false); |
| doMoveTests(dir1, dir3, false); |
| |
| } 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 |
| long time1 = attrs1.lastModifiedTime().toMillis(); |
| long time2 = attrs2.lastModifiedTime().toMillis(); |
| 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.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 other attributes when same provider |
| if (source.getFileSystem().provider() == target.getFileSystem().provider()) { |
| |
| // 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, boolean supportsLinks) |
| 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(dir2); |
| moveAndVerify(source, target); |
| target.delete(); |
| |
| /** |
| * Test: move regular file, target exists |
| */ |
| source = createSourceFile(dir1); |
| target = getTargetFile(dir2).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(dir2); |
| moveAndVerify(source, target, REPLACE_EXISTING); |
| target.delete(); |
| |
| /** |
| * Test: move regular file, target exists |
| */ |
| source = createSourceFile(dir1); |
| target = getTargetFile(dir2).createFile(); |
| moveAndVerify(source, target, REPLACE_EXISTING); |
| target.delete(); |
| |
| /** |
| * Test: move regular file, target exists and is empty directory |
| */ |
| source = createSourceFile(dir1); |
| target = getTargetFile(dir2).createDirectory(); |
| moveAndVerify(source, target, REPLACE_EXISTING); |
| target.delete(); |
| |
| /** |
| * Test: move regular file, target exists and is non-empty directory |
| */ |
| source = createSourceFile(dir1); |
| target = getTargetFile(dir2).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(dir2); |
| moveAndVerify(source, target); |
| target.delete(); |
| |
| /** |
| * Test: move empty directory, target exists |
| */ |
| source = createSourceDirectory(dir1); |
| target = getTargetFile(dir2).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(dir2); |
| moveAndVerify(source, target, REPLACE_EXISTING); |
| target.delete(); |
| |
| /** |
| * Test: move empty directory, target exists |
| */ |
| source = createSourceDirectory(dir1); |
| target = getTargetFile(dir2).createFile(); |
| moveAndVerify(source, target, REPLACE_EXISTING); |
| target.delete(); |
| |
| /** |
| * Test: move empty, target exists and is empty directory |
| */ |
| source = createSourceDirectory(dir1); |
| target = getTargetFile(dir2).createDirectory(); |
| moveAndVerify(source, target, REPLACE_EXISTING); |
| target.delete(); |
| |
| /** |
| * Test: move empty directory, target exists and is non-empty directory |
| */ |
| source = createSourceDirectory(dir1); |
| target = getTargetFile(dir2).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(dir2); |
| 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(dir2); |
| 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(dir2); |
| moveAndVerify(source, target); |
| target.delete(); |
| } |
| |
| /** |
| * Test: Move symbolic link, target exists |
| */ |
| if (supportsLinks) { |
| source = dir1.resolve("link").createSymbolicLink(dir2); |
| target = getTargetFile(dir2).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(dir2).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(dir2).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(dir2).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(dir2).createFile(); |
| moveAndVerify(source, target, REPLACE_EXISTING); |
| target.delete(); |
| } |
| |
| // -- misc. tests -- |
| |
| /** |
| * Test nulls |
| */ |
| source = createSourceFile(dir1); |
| target = getTargetFile(dir2); |
| 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(dir2); |
| 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)); |
| |
| // verify other attributes when same provider |
| if (source.getFileSystem().provider() == target.getFileSystem().provider()) { |
| |
| // 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 dir1, Path dir2, boolean supportsLinks) |
| throws IOException |
| { |
| Path source, target, link, entry; |
| |
| // -- regular file -- |
| |
| /** |
| * Test: move regular file, target does not exist |
| */ |
| source = createSourceFile(dir1); |
| target = getTargetFile(dir2); |
| copyAndVerify(source, target); |
| source.delete(); |
| target.delete(); |
| |
| /** |
| * Test: copy regular file, target exists |
| */ |
| source = createSourceFile(dir1); |
| target = getTargetFile(dir2).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(dir1); |
| target = getTargetFile(dir2); |
| copyAndVerify(source, target, REPLACE_EXISTING); |
| source.delete(); |
| target.delete(); |
| |
| /** |
| * Test: copy regular file, target exists |
| */ |
| source = createSourceFile(dir1); |
| target = getTargetFile(dir2).createFile(); |
| copyAndVerify(source, target, REPLACE_EXISTING); |
| source.delete(); |
| target.delete(); |
| |
| /** |
| * Test: copy regular file, target exists and is empty directory |
| */ |
| source = createSourceFile(dir1); |
| target = getTargetFile(dir2).createDirectory(); |
| copyAndVerify(source, target, REPLACE_EXISTING); |
| source.delete(); |
| target.delete(); |
| |
| /** |
| * Test: copy regular file, target exists and is non-empty directory |
| */ |
| source = createSourceFile(dir1); |
| target = getTargetFile(dir2).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(dir1); |
| target = getTargetFile(dir2); |
| copyAndVerify(source, target, COPY_ATTRIBUTES); |
| source.delete(); |
| target.delete(); |
| |
| |
| // -- directory -- |
| |
| /* |
| * Test: copy directory, target does not exist |
| */ |
| source = createSourceDirectory(dir1); |
| target = getTargetFile(dir2); |
| copyAndVerify(source, target); |
| source.delete(); |
| target.delete(); |
| |
| /** |
| * Test: copy directory, target exists |
| */ |
| source = createSourceDirectory(dir1); |
| target = getTargetFile(dir2).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(dir1); |
| target = getTargetFile(dir2); |
| copyAndVerify(source, target, REPLACE_EXISTING); |
| source.delete(); |
| target.delete(); |
| |
| /** |
| * Test: copy directory, target exists |
| */ |
| source = createSourceDirectory(dir1); |
| target = getTargetFile(dir2).createFile(); |
| copyAndVerify(source, target, REPLACE_EXISTING); |
| source.delete(); |
| target.delete(); |
| |
| /** |
| * Test: copy directory, target exists and is empty directory |
| */ |
| source = createSourceDirectory(dir1); |
| target = getTargetFile(dir2).createDirectory(); |
| copyAndVerify(source, target, REPLACE_EXISTING); |
| source.delete(); |
| target.delete(); |
| |
| /** |
| * Test: copy directory, target exists and is non-empty directory |
| */ |
| source = createSourceDirectory(dir1); |
| target = getTargetFile(dir2).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(dir1); |
| target = getTargetFile(dir2); |
| copyAndVerify(source, target, COPY_ATTRIBUTES); |
| source.delete(); |
| target.delete(); |
| |
| // -- symbolic links -- |
| |
| /** |
| * Test: Follow link |
| */ |
| if (supportsLinks) { |
| source = createSourceFile(dir1); |
| link = dir1.resolve("link").createSymbolicLink(source); |
| target = getTargetFile(dir2); |
| copyAndVerify(link, target); |
| link.delete(); |
| source.delete(); |
| } |
| |
| /** |
| * Test: Copy link (to file) |
| */ |
| if (supportsLinks) { |
| source = createSourceFile(dir1); |
| link = dir1.resolve("link").createSymbolicLink(source); |
| target = getTargetFile(dir2); |
| copyAndVerify(link, target, NOFOLLOW_LINKS); |
| link.delete(); |
| source.delete(); |
| } |
| |
| /** |
| * Test: Copy link (to directory) |
| */ |
| if (supportsLinks) { |
| source = dir1.resolve("mydir").createDirectory(); |
| link = dir1.resolve("link").createSymbolicLink(source); |
| target = getTargetFile(dir2); |
| copyAndVerify(link, target, NOFOLLOW_LINKS); |
| link.delete(); |
| source.delete(); |
| } |
| |
| /** |
| * Test: Copy broken link |
| */ |
| if (supportsLinks) { |
| assertTrue(source.notExists()); |
| link = dir1.resolve("link").createSymbolicLink(source); |
| target = getTargetFile(dir2); |
| 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 = dir1.resolve("link").createSymbolicLink(unc); |
| target = getTargetFile(dir2); |
| copyAndVerify(link, target, NOFOLLOW_LINKS); |
| link.delete(); |
| } |
| |
| // -- misc. tests -- |
| |
| /** |
| * Test nulls |
| */ |
| source = createSourceFile(dir1); |
| target = getTargetFile(dir2); |
| 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(dir1); |
| target = getTargetFile(dir2); |
| 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); |
| } |
| } |