8181761: add explicit @build actions for jdk.test.lib classes in all :tier2 tests
Reviewed-by: alanb
/*
* Copyright (c) 2008, 2017, 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 7006126 6950237 8006645
* @summary Unit test for java.nio.file.Files copy and move methods (use -Dseed=X to set PRNG seed)
* @library .. /test/lib
* @build jdk.test.lib.RandomFactory
* CopyAndMove PassThroughFileSystem
* @run main/othervm CopyAndMove
* @key randomness
*/
import java.nio.ByteBuffer;
import java.nio.file.*;
import static java.nio.file.Files.*;
import static java.nio.file.StandardCopyOption.*;
import static java.nio.file.LinkOption.*;
import java.nio.file.attribute.*;
import java.io.*;
import java.util.*;
import java.util.concurrent.TimeUnit;
import jdk.test.lib.RandomFactory;
public class CopyAndMove {
static final Random rand = RandomFactory.getRandom();
static boolean heads() { return rand.nextBoolean(); }
private static boolean testPosixAttributes = false;
public static void main(String[] args) throws Exception {
Path dir1 = TestUtil.createTemporaryDirectory();
try {
// Same directory
testPosixAttributes = getFileStore(dir1).supportsFileAttributeView("posix");
testCopyFileToFile(dir1, dir1, TestUtil.supportsLinks(dir1));
testMove(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);
testPosixAttributes = getFileStore(dir1).supportsFileAttributeView("posix") &&
getFileStore(dir2).supportsFileAttributeView("posix");
testCopyFileToFile(dir1, dir2, testSymbolicLinks);
testMove(dir1, dir2, testSymbolicLinks);
} finally {
TestUtil.removeAll(dir2);
}
// Target is location associated with custom provider
Path dir3 = PassThroughFileSystem.create().getPath(dir1.toString());
testPosixAttributes = getFileStore(dir1).supportsFileAttributeView("posix") &&
getFileStore(dir3).supportsFileAttributeView("posix");
testCopyFileToFile(dir1, dir3, false);
testMove(dir1, dir3, false);
// Test copy(InputStream,Path) and copy(Path,OutputStream)
testCopyInputStreamToFile();
testCopyFileToOuputStream();
} 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 if not a symbolic link
if (!attrs1.isSymbolicLink()) {
long time1 = attrs1.lastModifiedTime().to(TimeUnit.SECONDS);
long time2 = attrs2.lastModifiedTime().to(TimeUnit.SECONDS);
if (time1 != time2) {
System.err.format("File time for %s is %s\n", attrs1.fileKey(), attrs1.lastModifiedTime());
System.err.format("File time for %s is %s\n", attrs2.fileKey(), attrs2.lastModifiedTime());
assertTrue(false);
}
}
// 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 =
getFileAttributeView(file, UserDefinedFileAttributeView.class);
Map<String,ByteBuffer> result = new HashMap<>();
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.startsWith("Windows")) {
dosAttributes = readAttributes(source, DosFileAttributes.class, NOFOLLOW_LINKS);
basicAttributes = dosAttributes;
} else {
posixAttributes = readAttributes(source, PosixFileAttributes.class, NOFOLLOW_LINKS);
basicAttributes = posixAttributes;
}
if (basicAttributes == null)
basicAttributes = readAttributes(source, BasicFileAttributes.class, 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 = readSymbolicLink(source);
// read named attributes if available (and file is not a sym link)
if (!basicAttributes.isSymbolicLink() &&
getFileStore(source).supportsFileAttributeView("xattr"))
{
namedAttributes = readUserDefinedFileAttributes(source);
}
// move file
Path result = move(source, target, options);
assertTrue(result == target);
// verify source does not exist
assertTrue(notExists(source));
// 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 (!readSymbolicLink(target).equals(linkTarget))
throw new RuntimeException("Failed to verify move of symbolic link");
}
// verify basic attributes
checkBasicAttributes(basicAttributes,
readAttributes(target, BasicFileAttributes.class, NOFOLLOW_LINKS));
// verify other attributes when same provider
if (source.getFileSystem().provider() == target.getFileSystem().provider()) {
// verify POSIX attributes
if (posixAttributes != null &&
!basicAttributes.isSymbolicLink() &&
testPosixAttributes)
{
checkPosixAttributes(posixAttributes,
readAttributes(target, PosixFileAttributes.class, NOFOLLOW_LINKS));
}
// verify DOS attributes
if (dosAttributes != null && !basicAttributes.isSymbolicLink()) {
DosFileAttributes attrs =
readAttributes(target, DosFileAttributes.class, NOFOLLOW_LINKS);
checkDosAttributes(dosAttributes, attrs);
}
// verify named attributes
if (namedAttributes != null &&
getFileStore(target).supportsFileAttributeView("xattr"))
{
checkUserDefinedFileAttributes(namedAttributes,
readUserDefinedFileAttributes(target));
}
}
}
/**
* Tests all possible ways to invoke move
*/
static void testMove(Path dir1, Path dir2, boolean supportsLinks)
throws IOException
{
Path source, target, entry;
boolean sameDevice = getFileStore(dir1).equals(getFileStore(dir2));
// -- regular file --
/**
* Test: move regular file, target does not exist
*/
source = createSourceFile(dir1);
target = getTargetFile(dir2);
moveAndVerify(source, target);
delete(target);
/**
* Test: move regular file, target exists
*/
source = createSourceFile(dir1);
target = getTargetFile(dir2);
createFile(target);
try {
moveAndVerify(source, target);
throw new RuntimeException("FileAlreadyExistsException expected");
} catch (FileAlreadyExistsException x) {
}
delete(target);
createDirectory(target);
try {
moveAndVerify(source, target);
throw new RuntimeException("FileAlreadyExistsException expected");
} catch (FileAlreadyExistsException x) {
}
delete(source);
delete(target);
/**
* Test: move regular file, target does not exist
*/
source = createSourceFile(dir1);
target = getTargetFile(dir2);
moveAndVerify(source, target, REPLACE_EXISTING);
delete(target);
/**
* Test: move regular file, target exists
*/
source = createSourceFile(dir1);
target = getTargetFile(dir2);
createFile(target);
moveAndVerify(source, target, REPLACE_EXISTING);
delete(target);
/**
* Test: move regular file, target exists and is empty directory
*/
source = createSourceFile(dir1);
target = getTargetFile(dir2);
createDirectory(target);
moveAndVerify(source, target, REPLACE_EXISTING);
delete(target);
/**
* Test: move regular file, target exists and is non-empty directory
*/
source = createSourceFile(dir1);
target = getTargetFile(dir2);
createDirectory(target);
entry = target.resolve("foo");
createFile(entry);
try {
moveAndVerify(source, target);
throw new RuntimeException("FileAlreadyExistsException expected");
} catch (FileAlreadyExistsException x) {
}
delete(entry);
delete(source);
delete(target);
/**
* Test atomic move of regular file (same file store)
*/
source = createSourceFile(dir1);
target = getTargetFile(dir1);
moveAndVerify(source, target, ATOMIC_MOVE);
delete(target);
/**
* 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) {
}
delete(source);
}
// -- directories --
/*
* Test: move empty directory, target does not exist
*/
source = createSourceDirectory(dir1);
target = getTargetFile(dir2);
moveAndVerify(source, target);
delete(target);
/**
* Test: move empty directory, target exists
*/
source = createSourceDirectory(dir1);
target = getTargetFile(dir2);
createFile(target);
try {
moveAndVerify(source, target);
throw new RuntimeException("FileAlreadyExistsException expected");
} catch (FileAlreadyExistsException x) {
}
delete(target);
createDirectory(target);
try {
moveAndVerify(source, target);
throw new RuntimeException("FileAlreadyExistsException expected");
} catch (FileAlreadyExistsException x) {
}
delete(source);
delete(target);
/**
* Test: move empty directory, target does not exist
*/
source = createSourceDirectory(dir1);
target = getTargetFile(dir2);
moveAndVerify(source, target, REPLACE_EXISTING);
delete(target);
/**
* Test: move empty directory, target exists
*/
source = createSourceDirectory(dir1);
target = getTargetFile(dir2);
createFile(target);
moveAndVerify(source, target, REPLACE_EXISTING);
delete(target);
/**
* Test: move empty, target exists and is empty directory
*/
source = createSourceDirectory(dir1);
target = getTargetFile(dir2);
createDirectory(target);
moveAndVerify(source, target, REPLACE_EXISTING);
delete(target);
/**
* Test: move empty directory, target exists and is non-empty directory
*/
source = createSourceDirectory(dir1);
target = getTargetFile(dir2);
createDirectory(target);
entry = target.resolve("foo");
createFile(entry);
try {
moveAndVerify(source, target, REPLACE_EXISTING);
throw new RuntimeException("DirectoryNotEmptyException expected");
} catch (DirectoryNotEmptyException x) {
}
delete(entry);
delete(source);
delete(target);
/**
* Test: move non-empty directory (same file system)
*/
source = createSourceDirectory(dir1);
createFile(source.resolve("foo"));
target = getTargetFile(dir1);
moveAndVerify(source, target);
delete(target.resolve("foo"));
delete(target);
/**
* Test: move non-empty directory (different file store)
*/
if (!sameDevice) {
source = createSourceDirectory(dir1);
createFile(source.resolve("foo"));
target = getTargetFile(dir2);
try {
moveAndVerify(source, target);
throw new RuntimeException("IOException expected");
} catch (IOException x) {
}
delete(source.resolve("foo"));
delete(source);
}
/**
* Test atomic move of directory (same file store)
*/
source = createSourceDirectory(dir1);
createFile(source.resolve("foo"));
target = getTargetFile(dir1);
moveAndVerify(source, target, ATOMIC_MOVE);
delete(target.resolve("foo"));
delete(target);
// -- symbolic links --
/**
* Test: Move symbolic link to file, target does not exist
*/
if (supportsLinks) {
Path tmp = createSourceFile(dir1);
source = dir1.resolve("link");
createSymbolicLink(source, tmp);
target = getTargetFile(dir2);
moveAndVerify(source, target);
delete(target);
delete(tmp);
}
/**
* Test: Move symbolic link to directory, target does not exist
*/
if (supportsLinks) {
source = dir1.resolve("link");
createSymbolicLink(source, dir2);
target = getTargetFile(dir2);
moveAndVerify(source, target);
delete(target);
}
/**
* Test: Move broken symbolic link, target does not exists
*/
if (supportsLinks) {
Path tmp = Paths.get("doesnotexist");
source = dir1.resolve("link");
createSymbolicLink(source, tmp);
target = getTargetFile(dir2);
moveAndVerify(source, target);
delete(target);
}
/**
* Test: Move symbolic link, target exists
*/
if (supportsLinks) {
source = dir1.resolve("link");
createSymbolicLink(source, dir2);
target = getTargetFile(dir2);
createFile(target);
try {
moveAndVerify(source, target);
throw new RuntimeException("FileAlreadyExistsException expected");
} catch (FileAlreadyExistsException x) {
}
delete(source);
delete(target);
}
/**
* Test: Move regular file, target exists
*/
if (supportsLinks) {
source = dir1.resolve("link");
createSymbolicLink(source, dir2);
target = getTargetFile(dir2);
createFile(target);
moveAndVerify(source, target, REPLACE_EXISTING);
delete(target);
}
/**
* Test: move symbolic link, target exists and is empty directory
*/
if (supportsLinks) {
source = dir1.resolve("link");
createSymbolicLink(source, dir2);
target = getTargetFile(dir2);
createDirectory(target);
moveAndVerify(source, target, REPLACE_EXISTING);
delete(target);
}
/**
* Test: symbolic link, target exists and is non-empty directory
*/
if (supportsLinks) {
source = dir1.resolve("link");
createSymbolicLink(source, dir2);
target = getTargetFile(dir2);
createDirectory(target);
entry = target.resolve("foo");
createFile(entry);
try {
moveAndVerify(source, target);
throw new RuntimeException("FileAlreadyExistsException expected");
} catch (FileAlreadyExistsException x) {
}
delete(entry);
delete(source);
delete(target);
}
/**
* Test atomic move of symbolic link (same file store)
*/
if (supportsLinks) {
source = dir1.resolve("link");
createSymbolicLink(source, dir1);
target = getTargetFile(dir2);
createFile(target);
moveAndVerify(source, target, REPLACE_EXISTING);
delete(target);
}
// -- misc. tests --
/**
* Test nulls
*/
source = createSourceFile(dir1);
target = getTargetFile(dir2);
try {
move(null, target);
throw new RuntimeException("NullPointerException expected");
} catch (NullPointerException x) { }
try {
move(source, null);
throw new RuntimeException("NullPointerException expected");
} catch (NullPointerException x) { }
try {
move(source, target, (CopyOption[])null);
throw new RuntimeException("NullPointerException expected");
} catch (NullPointerException x) { }
try {
CopyOption[] opts = { REPLACE_EXISTING, null };
move(source, target, opts);
throw new RuntimeException("NullPointerException expected");
} catch (NullPointerException x) { }
delete(source);
/**
* Test UOE
*/
source = createSourceFile(dir1);
target = getTargetFile(dir2);
try {
move(source, target, new CopyOption() { });
} catch (UnsupportedOperationException x) { }
try {
move(source, target, REPLACE_EXISTING, new CopyOption() { });
} catch (UnsupportedOperationException x) { }
delete(source);
}
// copy source to target with verification
static void copyAndVerify(Path source, Path target, CopyOption... options)
throws IOException
{
Path result = copy(source, target, options);
assertTrue(result == target);
// 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 =
readAttributes(source, BasicFileAttributes.class, linkOptions);
// check hash if regular file
if (basicAttributes.isRegularFile())
assertTrue(computeHash(source) == computeHash(target));
// check link target if symbolic link
if (basicAttributes.isSymbolicLink())
assert(readSymbolicLink(source).equals(readSymbolicLink(target)));
// check that attributes are copied
if (copyAttributes && followLinks) {
checkBasicAttributes(basicAttributes,
readAttributes(source, BasicFileAttributes.class, 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")) &&
testPosixAttributes)
{
checkPosixAttributes(
readAttributes(source, PosixFileAttributes.class, linkOptions),
readAttributes(target, PosixFileAttributes.class, linkOptions));
}
// check DOS attributes are copied
if (os.startsWith("Windows")) {
checkDosAttributes(
readAttributes(source, DosFileAttributes.class, linkOptions),
readAttributes(target, DosFileAttributes.class, linkOptions));
}
// check named attributes are copied
if (followLinks &&
getFileStore(source).supportsFileAttributeView("xattr") &&
getFileStore(target).supportsFileAttributeView("xattr"))
{
checkUserDefinedFileAttributes(readUserDefinedFileAttributes(source),
readUserDefinedFileAttributes(target));
}
}
}
}
/**
* Tests all possible ways to invoke copy to copy a file to a file
*/
static void testCopyFileToFile(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);
delete(source);
delete(target);
/**
* Test: copy regular file, target exists
*/
source = createSourceFile(dir1);
target = getTargetFile(dir2);
createFile(target);
try {
copyAndVerify(source, target);
throw new RuntimeException("FileAlreadyExistsException expected");
} catch (FileAlreadyExistsException x) {
}
delete(target);
createDirectory(target);
try {
copyAndVerify(source, target);
throw new RuntimeException("FileAlreadyExistsException expected");
} catch (FileAlreadyExistsException x) {
}
delete(source);
delete(target);
/**
* Test: copy regular file, target does not exist
*/
source = createSourceFile(dir1);
target = getTargetFile(dir2);
copyAndVerify(source, target, REPLACE_EXISTING);
delete(source);
delete(target);
/**
* Test: copy regular file, target exists
*/
source = createSourceFile(dir1);
target = getTargetFile(dir2);
createFile(target);
copyAndVerify(source, target, REPLACE_EXISTING);
delete(source);
delete(target);
/**
* Test: copy regular file, target exists and is empty directory
*/
source = createSourceFile(dir1);
target = getTargetFile(dir2);
createDirectory(target);
copyAndVerify(source, target, REPLACE_EXISTING);
delete(source);
delete(target);
/**
* Test: copy regular file, target exists and is non-empty directory
*/
source = createSourceFile(dir1);
target = getTargetFile(dir2);
createDirectory(target);
entry = target.resolve("foo");
createFile(entry);
try {
copyAndVerify(source, target);
throw new RuntimeException("FileAlreadyExistsException expected");
} catch (FileAlreadyExistsException x) {
}
delete(entry);
delete(source);
delete(target);
/**
* Test: copy regular file + attributes
*/
source = createSourceFile(dir1);
target = getTargetFile(dir2);
copyAndVerify(source, target, COPY_ATTRIBUTES);
delete(source);
delete(target);
// -- directory --
/*
* Test: copy directory, target does not exist
*/
source = createSourceDirectory(dir1);
target = getTargetFile(dir2);
copyAndVerify(source, target);
delete(source);
delete(target);
/**
* Test: copy directory, target exists
*/
source = createSourceDirectory(dir1);
target = getTargetFile(dir2);
createFile(target);
try {
copyAndVerify(source, target);
throw new RuntimeException("FileAlreadyExistsException expected");
} catch (FileAlreadyExistsException x) {
}
delete(target);
createDirectory(target);
try {
copyAndVerify(source, target);
throw new RuntimeException("FileAlreadyExistsException expected");
} catch (FileAlreadyExistsException x) {
}
delete(source);
delete(target);
/**
* Test: copy directory, target does not exist
*/
source = createSourceDirectory(dir1);
target = getTargetFile(dir2);
copyAndVerify(source, target, REPLACE_EXISTING);
delete(source);
delete(target);
/**
* Test: copy directory, target exists
*/
source = createSourceDirectory(dir1);
target = getTargetFile(dir2);
createFile(target);
copyAndVerify(source, target, REPLACE_EXISTING);
delete(source);
delete(target);
/**
* Test: copy directory, target exists and is empty directory
*/
source = createSourceDirectory(dir1);
target = getTargetFile(dir2);
createDirectory(target);
copyAndVerify(source, target, REPLACE_EXISTING);
delete(source);
delete(target);
/**
* Test: copy directory, target exists and is non-empty directory
*/
source = createSourceDirectory(dir1);
target = getTargetFile(dir2);
createDirectory(target);
entry = target.resolve("foo");
createFile(entry);
try {
copyAndVerify(source, target, REPLACE_EXISTING);
throw new RuntimeException("DirectoryNotEmptyException expected");
} catch (DirectoryNotEmptyException x) {
}
delete(entry);
delete(source);
delete(target);
/*
* Test: copy directory + attributes
*/
source = createSourceDirectory(dir1);
target = getTargetFile(dir2);
copyAndVerify(source, target, COPY_ATTRIBUTES);
delete(source);
delete(target);
// -- symbolic links --
/**
* Test: Follow link
*/
if (supportsLinks) {
source = createSourceFile(dir1);
link = dir1.resolve("link");
createSymbolicLink(link, source);
target = getTargetFile(dir2);
copyAndVerify(link, target);
delete(link);
delete(source);
}
/**
* Test: Copy link (to file)
*/
if (supportsLinks) {
source = createSourceFile(dir1);
link = dir1.resolve("link");
createSymbolicLink(link, source);
target = getTargetFile(dir2);
copyAndVerify(link, target, NOFOLLOW_LINKS);
delete(link);
delete(source);
}
/**
* Test: Copy link (to directory)
*/
if (supportsLinks) {
source = dir1.resolve("mydir");
createDirectory(source);
link = dir1.resolve("link");
createSymbolicLink(link, source);
target = getTargetFile(dir2);
copyAndVerify(link, target, NOFOLLOW_LINKS);
delete(link);
delete(source);
}
/**
* Test: Copy broken link
*/
if (supportsLinks) {
assertTrue(notExists(source));
link = dir1.resolve("link");
createSymbolicLink(link, source);
target = getTargetFile(dir2);
copyAndVerify(link, target, NOFOLLOW_LINKS);
delete(link);
}
/**
* 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(link, unc);
target = getTargetFile(dir2);
copyAndVerify(link, target, NOFOLLOW_LINKS);
delete(link);
}
// -- misc. tests --
/**
* Test nulls
*/
source = createSourceFile(dir1);
target = getTargetFile(dir2);
try {
copy(source, null);
throw new RuntimeException("NullPointerException expected");
} catch (NullPointerException x) { }
try {
copy(source, target, (CopyOption[])null);
throw new RuntimeException("NullPointerException expected");
} catch (NullPointerException x) { }
try {
CopyOption[] opts = { REPLACE_EXISTING, null };
copy(source, target, opts);
throw new RuntimeException("NullPointerException expected");
} catch (NullPointerException x) { }
delete(source);
/**
* Test UOE
*/
source = createSourceFile(dir1);
target = getTargetFile(dir2);
try {
copy(source, target, new CopyOption() { });
} catch (UnsupportedOperationException x) { }
try {
copy(source, target, REPLACE_EXISTING, new CopyOption() { });
} catch (UnsupportedOperationException x) { }
delete(source);
}
/**
* Test copy from an input stream to a file
*/
static void testCopyInputStreamToFile() throws IOException {
testCopyInputStreamToFile(0);
for (int i=0; i<100; i++) {
testCopyInputStreamToFile(rand.nextInt(32000));
}
// FileAlreadyExistsException
Path target = createTempFile("blah", null);
try {
InputStream in = new ByteArrayInputStream(new byte[0]);
try {
copy(in, target);
throw new RuntimeException("FileAlreadyExistsException expected");
} catch (FileAlreadyExistsException ignore) { }
} finally {
delete(target);
}
Path tmpdir = createTempDirectory("blah");
try {
if (TestUtil.supportsLinks(tmpdir)) {
Path link = createSymbolicLink(tmpdir.resolve("link"),
tmpdir.resolve("target"));
try {
InputStream in = new ByteArrayInputStream(new byte[0]);
try {
copy(in, link);
throw new RuntimeException("FileAlreadyExistsException expected");
} catch (FileAlreadyExistsException ignore) { }
} finally {
delete(link);
}
}
} finally {
delete(tmpdir);
}
// nulls
try {
copy((InputStream)null, target);
throw new RuntimeException("NullPointerException expected");
} catch (NullPointerException ignore) { }
try {
copy(new ByteArrayInputStream(new byte[0]), (Path)null);
throw new RuntimeException("NullPointerException expected");
} catch (NullPointerException ignore) { }
}
static void testCopyInputStreamToFile(int size) throws IOException {
Path tmpdir = createTempDirectory("blah");
Path source = tmpdir.resolve("source");
Path target = tmpdir.resolve("target");
try {
boolean testReplaceExisting = rand.nextBoolean();
// create source file
byte[] b = new byte[size];
rand.nextBytes(b);
write(source, b);
// target file might already exist
if (testReplaceExisting && rand.nextBoolean()) {
write(target, new byte[rand.nextInt(512)]);
}
// copy from stream to file
InputStream in = new FileInputStream(source.toFile());
try {
long n;
if (testReplaceExisting) {
n = copy(in, target, StandardCopyOption.REPLACE_EXISTING);
} else {
n = copy(in, target);
}
assertTrue(in.read() == -1); // EOF
assertTrue(n == size);
assertTrue(size(target) == size);
} finally {
in.close();
}
// check file
byte[] read = readAllBytes(target);
assertTrue(Arrays.equals(read, b));
} finally {
deleteIfExists(source);
deleteIfExists(target);
delete(tmpdir);
}
}
/**
* Test copy from file to output stream
*/
static void testCopyFileToOuputStream() throws IOException {
testCopyFileToOuputStream(0);
for (int i=0; i<100; i++) {
testCopyFileToOuputStream(rand.nextInt(32000));
}
// nulls
try {
copy((Path)null, new ByteArrayOutputStream());
throw new RuntimeException("NullPointerException expected");
} catch (NullPointerException ignore) { }
try {
Path source = createTempFile("blah", null);
delete(source);
copy(source, (OutputStream)null);
throw new RuntimeException("NullPointerException expected");
} catch (NullPointerException ignore) { }
}
static void testCopyFileToOuputStream(int size) throws IOException {
Path source = createTempFile("blah", null);
try {
byte[] b = new byte[size];
rand.nextBytes(b);
write(source, b);
ByteArrayOutputStream out = new ByteArrayOutputStream();
long n = copy(source, out);
assertTrue(n == size);
assertTrue(out.size() == size);
byte[] read = out.toByteArray();
assertTrue(Arrays.equals(read, b));
// check output stream is open
out.write(0);
assertTrue(out.size() == size+1);
} finally {
delete(source);
}
}
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;
try (InputStream in = newInputStream(file)) {
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);
}
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(file);
byte[] bytes = new byte[rand.nextInt(128*1024)];
rand.nextBytes(bytes);
try (OutputStream out = newOutputStream(file)) {
out.write(bytes);
}
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(subdir);
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 = isDirectory(file, NOFOLLOW_LINKS);
if (isUnix) {
Set<PosixFilePermission> perms =
getPosixFilePermissions(file, NOFOLLOW_LINKS);
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);
}
}
setPosixFilePermissions(file, perms);
}
if (isWindows) {
DosFileAttributeView view =
getFileAttributeView(file, DosFileAttributeView.class, NOFOLLOW_LINKS);
// only set or unset the hidden attribute
view.setHidden(heads());
}
boolean addUserDefinedFileAttributes = heads() &&
getFileStore(file).supportsFileAttributeView("xattr");
// remove this when copying a direcory copies its named streams
if (isWindows && isDirectory) addUserDefinedFileAttributes = false;
if (addUserDefinedFileAttributes) {
UserDefinedFileAttributeView view =
getFileAttributeView(file, 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);
}
}