/*
* Copyright 2014 Red Hat, Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.vertx.test.core;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.vertx.core.AsyncResult;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.file.AsyncFile;
import io.vertx.core.file.FileProps;
import io.vertx.core.file.FileSystemException;
import io.vertx.core.file.FileSystemProps;
import io.vertx.core.file.OpenOptions;
import io.vertx.core.file.impl.AsyncFileImpl;
import io.vertx.core.impl.Utils;
import io.vertx.core.json.JsonObject;
import io.vertx.core.streams.Pump;
import io.vertx.core.streams.ReadStream;
import io.vertx.core.streams.WriteStream;
import org.junit.Assume;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.GroupPrincipal;
import java.nio.file.attribute.PosixFileAttributes;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.nio.file.attribute.UserPrincipal;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import static io.vertx.test.core.TestUtils.*;
/**
* @author <a href="http://tfox.org">Tim Fox</a>
*/
public class FileSystemTest extends VertxTestBase {
private static final String DEFAULT_DIR_PERMS = "rwxr-xr-x";
private static final String DEFAULT_FILE_PERMS = "rw-r--r--";
private String pathSep;
private String testDir;
@Rule
public TemporaryFolder testFolder = new TemporaryFolder();
public void setUp() throws Exception {
super.setUp();
java.nio.file.FileSystem fs = FileSystems.getDefault();
pathSep = fs.getSeparator();
File ftestDir = testFolder.newFolder();
testDir = ftestDir.toString();
}
@Test
public void testIllegalArguments() throws Exception {
assertNullPointerException(() -> vertx.fileSystem().copy(null, "ignored", h -> {}));
assertNullPointerException(() -> vertx.fileSystem().copy("ignored", null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().copyBlocking(null, "ignored"));
assertNullPointerException(() -> vertx.fileSystem().copyBlocking("ignored", null));
assertNullPointerException(() -> vertx.fileSystem().copyRecursive(null, "ignored", true, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().copyRecursive("ignored", null, true, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().copyRecursiveBlocking(null, "ignored", true));
assertNullPointerException(() -> vertx.fileSystem().copyRecursiveBlocking("ignored", null, true));
assertNullPointerException(() -> vertx.fileSystem().move(null, "ignored", h -> {}));
assertNullPointerException(() -> vertx.fileSystem().move("ignored", null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().moveBlocking(null, "ignored"));
assertNullPointerException(() -> vertx.fileSystem().moveBlocking("ignored", null));
assertNullPointerException(() -> vertx.fileSystem().truncate(null, 0, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().truncateBlocking(null, 0));
assertNullPointerException(() -> vertx.fileSystem().chmod(null, "ignored", h -> {}));
assertNullPointerException(() -> vertx.fileSystem().chmod("ignored", null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().chmodBlocking(null, "ignored"));
assertNullPointerException(() -> vertx.fileSystem().chmodBlocking("ignored", null));
assertNullPointerException(() -> vertx.fileSystem().chmodRecursive(null, "ignored", "ignored", h -> {}));
assertNullPointerException(() -> vertx.fileSystem().chmodRecursive("ignored", null, "ignored", h -> {}));
assertNullPointerException(() -> vertx.fileSystem().chmodRecursiveBlocking(null, "ignored", "ignored"));
assertNullPointerException(() -> vertx.fileSystem().chmodRecursiveBlocking("ignored", null, "ignored"));
assertNullPointerException(() -> vertx.fileSystem().chown(null, "ignored", "ignored", h -> {}));
assertNullPointerException(() -> vertx.fileSystem().chownBlocking(null, "ignored", "ignored"));
assertNullPointerException(() -> vertx.fileSystem().props(null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().propsBlocking(null));
assertNullPointerException(() -> vertx.fileSystem().lprops(null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().lpropsBlocking(null));
assertNullPointerException(() -> vertx.fileSystem().link(null, "ignored", h -> {}));
assertNullPointerException(() -> vertx.fileSystem().link("ignored", null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().linkBlocking(null, "ignored"));
assertNullPointerException(() -> vertx.fileSystem().linkBlocking("ignored", null));
assertNullPointerException(() -> vertx.fileSystem().symlink(null, "ignored", h -> {}));
assertNullPointerException(() -> vertx.fileSystem().symlink("ignored", null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().symlinkBlocking(null, "ignored"));
assertNullPointerException(() -> vertx.fileSystem().symlinkBlocking("ignored", null));
assertNullPointerException(() -> vertx.fileSystem().unlink(null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().unlinkBlocking(null));
assertNullPointerException(() -> vertx.fileSystem().readSymlink(null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().readSymlinkBlocking(null));
assertNullPointerException(() -> vertx.fileSystem().delete(null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().deleteBlocking(null));
assertNullPointerException(() -> vertx.fileSystem().deleteRecursive(null, true, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().deleteRecursiveBlocking(null, true));
assertNullPointerException(() -> vertx.fileSystem().mkdir(null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().mkdirBlocking(null));
assertNullPointerException(() -> vertx.fileSystem().mkdir(null, "ignored", h -> {}));
assertNullPointerException(() -> vertx.fileSystem().mkdirBlocking(null, "ignored"));
assertNullPointerException(() -> vertx.fileSystem().mkdirs(null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().mkdirsBlocking(null));
assertNullPointerException(() -> vertx.fileSystem().mkdirs(null, "ignored", h -> {}));
assertNullPointerException(() -> vertx.fileSystem().mkdirsBlocking(null, "ignored"));
assertNullPointerException(() -> vertx.fileSystem().readDir(null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().readDirBlocking(null));
assertNullPointerException(() -> vertx.fileSystem().readDir(null, "ignored", h -> {}));
assertNullPointerException(() -> vertx.fileSystem().readDirBlocking(null, "ignored"));
assertNullPointerException(() -> vertx.fileSystem().readFile(null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().readFileBlocking(null));
assertNullPointerException(() -> vertx.fileSystem().writeFile(null, Buffer.buffer(), h -> {}));
assertNullPointerException(() -> vertx.fileSystem().writeFile("ignored", null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().writeFileBlocking(null, Buffer.buffer()));
assertNullPointerException(() -> vertx.fileSystem().writeFileBlocking("ignored", null));
assertNullPointerException(() -> vertx.fileSystem().open(null, new OpenOptions(), h -> {}));
assertNullPointerException(() -> vertx.fileSystem().open("ignored", null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().openBlocking(null, new OpenOptions()));
assertNullPointerException(() -> vertx.fileSystem().openBlocking("ignored", null));
assertNullPointerException(() -> vertx.fileSystem().createFile(null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().createFileBlocking(null));
assertNullPointerException(() -> vertx.fileSystem().createFile(null, "ignored", h -> {}));
assertNullPointerException(() -> vertx.fileSystem().createFileBlocking(null, "ignored"));
assertNullPointerException(() -> vertx.fileSystem().exists(null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().existsBlocking(null));
assertNullPointerException(() -> vertx.fileSystem().fsProps(null, h -> {}));
assertNullPointerException(() -> vertx.fileSystem().fsPropsBlocking(null));
String fileName = "some-file.dat";
AsyncFile asyncFile = vertx.fileSystem().openBlocking(testDir + pathSep + fileName, new OpenOptions());
assertNullPointerException(() -> asyncFile.write(null));
assertIllegalArgumentException(() -> asyncFile.setWriteQueueMaxSize(1));
assertIllegalArgumentException(() -> asyncFile.setWriteQueueMaxSize(0));
assertIllegalArgumentException(() -> asyncFile.setWriteQueueMaxSize(-1));
assertNullPointerException(() -> asyncFile.write(null, 0, h -> {}));
assertNullPointerException(() -> asyncFile.write(Buffer.buffer(), 0, null));
assertIllegalArgumentException(() -> asyncFile.write(Buffer.buffer(), -1, h -> {}));
assertNullPointerException(() -> asyncFile.read(null, 0, 0, 0, h -> {}));
assertNullPointerException(() -> asyncFile.read(Buffer.buffer(), 0, 0, 0, null));
assertIllegalArgumentException(() -> asyncFile.read(Buffer.buffer(), -1, 0, 0, h -> {}));
assertIllegalArgumentException(() -> asyncFile.read(Buffer.buffer(), 0, -1, 0, h -> {}));
assertIllegalArgumentException(() -> asyncFile.read(Buffer.buffer(), 0, 0, -1, h -> {}));
}
@Test
public void testSimpleCopy() throws Exception {
String source = "foo.txt";
String target = "bar.txt";
createFileWithJunk(source, 100);
testCopy(source, target, false, true, v-> {
assertTrue(fileExists(source));
assertTrue(fileExists(target));
});
await();
}
@Test
public void testSimpleCopyFileAlreadyExists() throws Exception {
String source = "foo.txt";
String target = "bar.txt";
createFileWithJunk(source, 100);
createFileWithJunk(target, 100);
testCopy(source, target, false, false, v -> {
assertTrue(fileExists(source));
assertTrue(fileExists(target));
});
await();
}
@Test
public void testCopyIntoDir() throws Exception {
String source = "foo.txt";
String dir = "some-dir";
String target = dir + pathSep + "bar.txt";
mkDir(dir);
createFileWithJunk(source, 100);
testCopy(source, target, false, true, v -> {
assertTrue(fileExists(source));
assertTrue(fileExists(target));
});
await();
}
@Test
public void testCopyEmptyDir() throws Exception {
String source = "some-dir";
String target = "some-other-dir";
mkDir(source);
testCopy(source, target, false, true, v -> {
assertTrue(fileExists(source));
assertTrue(fileExists(target));
});
await();
}
@Test
public void testCopyNonEmptyDir() throws Exception {
String source = "some-dir";
String target = "some-other-dir";
String file1 = pathSep + "somefile.bar";
mkDir(source);
createFileWithJunk(source + file1, 100);
testCopy(source, target, false, true, v -> {
assertTrue(fileExists(source));
assertTrue(fileExists(target));
assertFalse(fileExists(target + file1));
});
await();
}
@Test
public void testFailCopyDirAlreadyExists() throws Exception {
String source = "some-dir";
String target = "some-other-dir";
mkDir(source);
mkDir(target);
testCopy(source, target, false, false, v -> {
assertTrue(fileExists(source));
assertTrue(fileExists(target));
});
await();
}
@Test
public void testRecursiveCopy() throws Exception {
String dir = "some-dir";
String file1 = pathSep + "file1.dat";
String file2 = pathSep + "index.html";
String dir2 = "next-dir";
String file3 = pathSep + "blah.java";
mkDir(dir);
createFileWithJunk(dir + file1, 100);
createFileWithJunk(dir + file2, 100);
mkDir(dir + pathSep + dir2);
createFileWithJunk(dir + pathSep + dir2 + file3, 100);
String target = "some-other-dir";
testCopy(dir, target, true, true, v -> {
assertTrue(fileExists(dir));
assertTrue(fileExists(target));
assertTrue(fileExists(target + file1));
assertTrue(fileExists(target + file2));
assertTrue(fileExists(target + pathSep + dir2 + file3));
});
await();
}
private void testCopy(String source, String target, boolean recursive,
boolean shouldPass, Handler<Void> afterOK) {
if (recursive) {
vertx.fileSystem().copyRecursive(testDir + pathSep + source, testDir + pathSep + target, true, createHandler(shouldPass, afterOK));
} else {
vertx.fileSystem().copy(testDir + pathSep + source, testDir + pathSep + target, createHandler(shouldPass, afterOK));
}
}
@Test
public void testSimpleMove() throws Exception {
String source = "foo.txt";
String target = "bar.txt";
createFileWithJunk(source, 100);
testMove(source, target, true, v -> {
assertFalse(fileExists(source));
assertTrue(fileExists(target));
});
await();
}
@Test
public void testSimpleMoveFileAlreadyExists() throws Exception {
String source = "foo.txt";
String target = "bar.txt";
createFileWithJunk(source, 100);
createFileWithJunk(target, 100);
testMove(source, target, false, v -> {
assertTrue(fileExists(source));
assertTrue(fileExists(target));
});
await();
}
@Test
public void testMoveEmptyDir() throws Exception {
String source = "some-dir";
String target = "some-other-dir";
mkDir(source);
testMove(source, target, true, v -> {
assertFalse(fileExists(source));
assertTrue(fileExists(target));
});
await();
}
@Test
public void testMoveEmptyDirTargetExists() throws Exception {
String source = "some-dir";
String target = "some-other-dir";
mkDir(source);
mkDir(target);
testMove(source, target, false, v -> {
assertTrue(fileExists(source));
assertTrue(fileExists(target));
});
await();
}
@Test
public void testMoveNonEmptyDir() throws Exception {
String dir = "some-dir";
String file1 = pathSep + "file1.dat";
String file2 = pathSep + "index.html";
String dir2 = "next-dir";
String file3 = pathSep + "blah.java";
mkDir(dir);
createFileWithJunk(dir + file1, 100);
createFileWithJunk(dir + file2, 100);
mkDir(dir + pathSep + dir2);
createFileWithJunk(dir + pathSep + dir2 + file3, 100);
String target = "some-other-dir";
testMove(dir, target, true, v -> {
assertFalse(fileExists(dir));
assertTrue(fileExists(target));
assertTrue(fileExists(target + file1));
assertTrue(fileExists(target + file2));
assertTrue(fileExists(target + pathSep + dir2 + file3));
});
await();
}
private void testMove(String source, String target, boolean shouldPass, Handler<Void> afterOK) throws Exception {
vertx.fileSystem().move(testDir + pathSep + source, testDir + pathSep + target, createHandler(shouldPass, afterOK));
}
@Test
public void testTruncate() throws Exception {
String file1 = "some-file.dat";
long initialLen = 1000;
long truncatedLen = 534;
createFileWithJunk(file1, initialLen);
assertEquals(initialLen, fileLength(file1));
testTruncate(file1, truncatedLen, true, v -> {
assertEquals(truncatedLen, fileLength(file1));
});
await();
}
@Test
public void testTruncateExtendsFile() throws Exception {
String file1 = "some-file.dat";
long initialLen = 500;
long truncatedLen = 1000;
createFileWithJunk(file1, initialLen);
assertEquals(initialLen, fileLength(file1));
testTruncate(file1, truncatedLen, true, v -> {
assertEquals(truncatedLen, fileLength(file1));
});
await();
}
@Test
public void testTruncateFileDoesNotExist() throws Exception {
String file1 = "some-file.dat";
long truncatedLen = 534;
testTruncate(file1, truncatedLen, false, null);
await();
}
private void testTruncate(String file, long truncatedLen, boolean shouldPass,
Handler<Void> afterOK) throws Exception {
vertx.fileSystem().truncate(testDir + pathSep + file, truncatedLen, createHandler(shouldPass, afterOK));
}
@Test
public void testChmodNonRecursive1() throws Exception {
testChmodNonRecursive("rw-------");
}
@Test
public void testChmodNonRecursive2() throws Exception {
testChmodNonRecursive("rwx------");
}
@Test
public void testChmodNonRecursive3() throws Exception {
testChmodNonRecursive("rw-rw-rw-");
}
@Test
public void testChmodNonRecursive4() throws Exception {
testChmodNonRecursive("rw-r--r--");
}
@Test
public void testChmodNonRecursive5() throws Exception {
testChmodNonRecursive("rw--w--w-");
}
@Test
public void testChmodNonRecursive6() throws Exception {
testChmodNonRecursive("rw-rw-rw-");
}
private void testChmodNonRecursive(String perms) throws Exception {
String file1 = "some-file.dat";
createFileWithJunk(file1, 100);
testChmod(file1, perms, null, true, v -> {
azzertPerms(perms, file1);
deleteFile(file1);
});
await();
}
private void azzertPerms(String perms, String file1) {
if (!Utils.isWindows()) {
assertEquals(perms, getPerms(file1));
}
}
@Test
public void testChmodRecursive1() throws Exception {
testChmodRecursive("rw-------", "rwx------");
}
@Test
public void testChmodRecursive2() throws Exception {
testChmodRecursive("rwx------", "rwx------");
}
@Test
public void testChmodRecursive3() throws Exception {
testChmodRecursive("rw-rw-rw-", "rwxrw-rw-");
}
@Test
public void testChmodRecursive4() throws Exception {
testChmodRecursive("rw-r--r--", "rwxr--r--");
}
@Test
public void testChmodRecursive5() throws Exception {
testChmodRecursive("rw--w--w-", "rwx-w--w-");
}
@Test
public void testChmodRecursive6() throws Exception {
testChmodRecursive("rw-rw-rw-", "rwxrw-rw-");
}
private void testChmodRecursive(String perms, String dirPerms) throws Exception {
String dir = "some-dir";
String file1 = pathSep + "file1.dat";
String file2 = pathSep + "index.html";
String dir2 = "next-dir";
String file3 = pathSep + "blah.java";
mkDir(dir);
createFileWithJunk(dir + file1, 100);
createFileWithJunk(dir + file2, 100);
mkDir(dir + pathSep + dir2);
createFileWithJunk(dir + pathSep + dir2 + file3, 100);
testChmod(dir, perms, dirPerms, true, v -> {
azzertPerms(dirPerms, dir);
azzertPerms(perms, dir + file1);
azzertPerms(perms, dir + file2);
azzertPerms(dirPerms, dir + pathSep + dir2);
azzertPerms(perms, dir + pathSep + dir2 + file3);
deleteDir(dir);
});
await();
}
@Test
public void testChownToRootFails() throws Exception {
testChownFails("root");
}
@Test
public void testChownToNotExistingUserFails() throws Exception {
testChownFails("jfhfhjejweg");
}
private void testChownFails(String user) throws Exception {
String file1 = "some-file.dat";
createFileWithJunk(file1, 100);
vertx.fileSystem().chown(testDir + pathSep + file1, user, null, ar -> {
deleteFile(file1);
assertTrue(ar.failed());
testComplete();
});
await();
}
@Test
public void testChownToOwnUser() throws Exception {
String file1 = "some-file.dat";
createFileWithJunk(file1, 100);
String fullPath = testDir + pathSep + file1;
Path path = Paths.get(fullPath);
UserPrincipal owner = Files.getOwner(path);
String user = owner.getName();
vertx.fileSystem().chown(fullPath, user, null, ar -> {
deleteFile(file1);
assertTrue(ar.succeeded());
testComplete();
});
await();
}
@Test
public void testChownToOwnGroup() throws Exception {
// Not supported in WindowsFileSystemProvider
Assume.assumeFalse(Utils.isWindows());
String file1 = "some-file.dat";
createFileWithJunk(file1, 100);
String fullPath = testDir + pathSep + file1;
Path path = Paths.get(fullPath);
GroupPrincipal group = Files.readAttributes(path, PosixFileAttributes.class, LinkOption.NOFOLLOW_LINKS).group();
vertx.fileSystem().chown(fullPath, null, group.getName(), ar -> {
deleteFile(file1);
assertTrue(ar.succeeded());
testComplete();
});
await();
}
private void testChmod(String file, String perms, String dirPerms,
boolean shouldPass, Handler<Void> afterOK) throws Exception {
if (Files.isDirectory(Paths.get(testDir + pathSep + file))) {
azzertPerms(DEFAULT_DIR_PERMS, file);
} else {
azzertPerms(DEFAULT_FILE_PERMS, file);
}
if (dirPerms != null) {
vertx.fileSystem().chmodRecursive(testDir + pathSep + file, perms, dirPerms, createHandler(shouldPass, afterOK));
} else {
vertx.fileSystem().chmod(testDir + pathSep + file, perms, createHandler(shouldPass, afterOK));
}
}
@Test
public void testProps() throws Exception {
String fileName = "some-file.txt";
long fileSize = 1234;
// The times are quite inaccurate so we give 1 second leeway
long start = 1000 * (System.currentTimeMillis() / 1000 - 1);
createFileWithJunk(fileName, fileSize);
testProps(fileName, false, true, st -> {
assertNotNull(st);
assertEquals(fileSize, st.size());
assertTrue(st.creationTime() >= start);
assertTrue(st.lastAccessTime() >= start);
assertTrue(st.lastModifiedTime() >= start);
assertFalse(st.isDirectory());
assertTrue(st.isRegularFile());
assertFalse(st.isSymbolicLink());
});
await();
}
@Test
public void testPropsFileDoesNotExist() throws Exception {
String fileName = "some-file.txt";
testProps(fileName, false, false, null);
await();
}
@Test
public void testPropsFollowLink() throws Exception {
// Symlinks require a modified security policy in Windows. -- See http://stackoverflow.com/questions/23217460/how-to-create-soft-symbolic-link-using-java-nio-files
Assume.assumeFalse(Utils.isWindows());
String fileName = "some-file.txt";
long fileSize = 1234;
// The times are quite inaccurate so we give 1 second leeway
long start = 1000 * (System.currentTimeMillis() / 1000 - 1);
createFileWithJunk(fileName, fileSize);
long end = 1000 * (System.currentTimeMillis() / 1000 + 1);
String linkName = "some-link.txt";
Files.createSymbolicLink(Paths.get(testDir + pathSep + linkName), Paths.get(fileName));
testProps(linkName, false, true, st -> {
assertNotNull(st);
assertEquals(fileSize, st.size());
assertTrue(st.creationTime() >= start);
assertTrue(st.creationTime() <= end);
assertTrue(st.lastAccessTime() >= start);
assertTrue(st.lastAccessTime() <= end);
assertTrue(st.lastModifiedTime() >= start);
assertTrue(st.lastModifiedTime() <= end);
assertFalse(st.isDirectory());
assertFalse(st.isOther());
assertTrue(st.isRegularFile());
assertFalse(st.isSymbolicLink());
});
await();
}
@Test
public void testPropsDontFollowLink() throws Exception {
// Symlinks require a modified security policy in Windows. -- See http://stackoverflow.com/questions/23217460/how-to-create-soft-symbolic-link-using-java-nio-files
Assume.assumeFalse(Utils.isWindows());
String fileName = "some-file.txt";
long fileSize = 1234;
createFileWithJunk(fileName, fileSize);
String linkName = "some-link.txt";
Files.createSymbolicLink(Paths.get(testDir + pathSep + linkName), Paths.get(fileName));
testProps(linkName, true, true, st -> {
assertNotNull(st != null);
assertTrue(st.isSymbolicLink());
});
await();
}
private void testProps(String fileName, boolean link, boolean shouldPass,
Handler<FileProps> afterOK) throws Exception {
Handler<AsyncResult<FileProps>> handler = ar -> {
if (ar.failed()) {
if (shouldPass) {
fail(ar.cause().getMessage());
} else {
assertTrue(ar.cause() instanceof io.vertx.core.file.FileSystemException);
if (afterOK != null) {
afterOK.handle(ar.result());
}
testComplete();
}
} else {
if (shouldPass) {
if (afterOK != null) {
afterOK.handle(ar.result());
}
testComplete();
} else {
fail("stat should fail");
}
}
};
if (link) {
vertx.fileSystem().lprops(testDir + pathSep + fileName, handler);
} else {
vertx.fileSystem().props(testDir + pathSep + fileName, handler);
}
}
@Test
public void testLink() throws Exception {
String fileName = "some-file.txt";
long fileSize = 1234;
createFileWithJunk(fileName, fileSize);
String linkName = "some-link.txt";
testLink(linkName, fileName, false, true, v -> {
assertEquals(fileSize, fileLength(linkName));
assertFalse(Files.isSymbolicLink(Paths.get(testDir + pathSep + linkName)));
});
await();
}
@Test
public void testSymLink() throws Exception {
// Symlinks require a modified security policy in Windows. -- See http://stackoverflow.com/questions/23217460/how-to-create-soft-symbolic-link-using-java-nio-files
Assume.assumeFalse(Utils.isWindows());
String fileName = "some-file.txt";
long fileSize = 1234;
createFileWithJunk(fileName, fileSize);
String symlinkName = "some-sym-link.txt";
testLink(symlinkName, fileName, true, true, v -> {
assertEquals(fileSize, fileLength(symlinkName));
assertTrue(Files.isSymbolicLink(Paths.get(testDir + pathSep + symlinkName)));
// Now try reading it
String read = vertx.fileSystem().readSymlinkBlocking(testDir + pathSep + symlinkName);
assertEquals(fileName, read);
});
await();
}
private void testLink(String from, String to, boolean symbolic,
boolean shouldPass, Handler<Void> afterOK) throws Exception {
if (symbolic) {
// Symlink is relative
vertx.fileSystem().symlink(testDir + pathSep + from, to, createHandler(shouldPass, afterOK));
} else {
vertx.fileSystem().link(testDir + pathSep + from, testDir + pathSep + to, createHandler(shouldPass, afterOK));
}
}
@Test
public void testUnlink() throws Exception {
String fileName = "some-file.txt";
long fileSize = 1234;
createFileWithJunk(fileName, fileSize);
String linkName = "some-link.txt";
Files.createLink(Paths.get(testDir + pathSep + linkName), Paths.get(testDir + pathSep + fileName));
assertEquals(fileSize, fileLength(linkName));
vertx.fileSystem().unlink(testDir + pathSep + linkName, createHandler(true, v -> assertFalse(fileExists(linkName))));
await();
}
@Test
public void testReadSymLink() throws Exception {
// Symlinks require a modified security policy in Windows. -- See http://stackoverflow.com/questions/23217460/how-to-create-soft-symbolic-link-using-java-nio-files
Assume.assumeFalse(Utils.isWindows());
String fileName = "some-file.txt";
long fileSize = 1234;
createFileWithJunk(fileName, fileSize);
String linkName = "some-link.txt";
Files.createSymbolicLink(Paths.get(testDir + pathSep + linkName), Paths.get(fileName));
vertx.fileSystem().readSymlink(testDir + pathSep + linkName, ar -> {
if (ar.failed()) {
fail(ar.cause().getMessage());
} else {
assertEquals(fileName, ar.result());
testComplete();
}
});
await();
}
@Test
public void testSimpleDelete() throws Exception {
String fileName = "some-file.txt";
createFileWithJunk(fileName, 100);
assertTrue(fileExists(fileName));
testDelete(fileName, false, true, v -> {
assertFalse(fileExists(fileName));
});
await();
}
@Test
public void testDeleteEmptyDir() throws Exception {
String dirName = "some-dir";
mkDir(dirName);
assertTrue(fileExists(dirName));
testDelete(dirName, false, true, v -> {
assertFalse(fileExists(dirName));
});
await();
}
@Test
public void testDeleteNonExistent() throws Exception {
String dirName = "some-dir";
assertFalse(fileExists(dirName));
testDelete(dirName, false, false, null);
await();
}
@Test
public void testDeleteNonEmptyFails() throws Exception {
String dirName = "some-dir";
mkDir(dirName);
String file1 = "some-file.txt";
createFileWithJunk(dirName + pathSep + file1, 100);
testDelete(dirName, false, false, null);
await();
}
@Test
public void testDeleteRecursive() throws Exception {
String dir = "some-dir";
String file1 = pathSep + "file1.dat";
String file2 = pathSep + "index.html";
String dir2 = "next-dir";
String file3 = pathSep + "blah.java";
mkDir(dir);
createFileWithJunk(dir + file1, 100);
createFileWithJunk(dir + file2, 100);
mkDir(dir + pathSep + dir2);
createFileWithJunk(dir + pathSep + dir2 + file3, 100);
testDelete(dir, true, true, v -> {
assertFalse(fileExists(dir));
});
await();
}
private void testDelete(String fileName, boolean recursive, boolean shouldPass,
Handler<Void> afterOK) throws Exception {
if (recursive) {
vertx.fileSystem().deleteRecursive(testDir + pathSep + fileName, recursive, createHandler(shouldPass, afterOK));
} else {
vertx.fileSystem().delete(testDir + pathSep + fileName, createHandler(shouldPass, afterOK));
}
}
@Test
public void testMkdirSimple() throws Exception {
String dirName = "some-dir";
testMkdir(dirName, null, false, true, v -> {
assertTrue(fileExists(dirName));
assertTrue(Files.isDirectory(Paths.get(testDir + pathSep + dirName)));
});
await();
}
@Test
public void testMkdirWithParentsFails() throws Exception {
String dirName = "top-dir" + pathSep + "some-dir";
testMkdir(dirName, null, false, false, null);
await();
}
@Test
public void testMkdirWithPerms() throws Exception {
String dirName = "some-dir";
String perms = "rwx--x--x";
testMkdir(dirName, perms, false, true, v -> {
assertTrue(fileExists(dirName));
assertTrue(Files.isDirectory(Paths.get(testDir + pathSep + dirName)));
azzertPerms(perms, dirName);
});
await();
}
@Test
public void testMkdirCreateParents() throws Exception {
String dirName = "top-dir" + pathSep + "/some-dir";
testMkdir(dirName, null, true, true, v -> {
assertTrue(fileExists(dirName));
assertTrue(Files.isDirectory(Paths.get(testDir + pathSep + dirName)));
});
await();
}
@Test
public void testMkdirCreateParentsWithPerms() throws Exception {
String dirName = "top-dir" + pathSep + "/some-dir";
String perms = "rwx--x--x";
testMkdir(dirName, perms, true, true, v -> {
assertTrue(fileExists(dirName));
assertTrue(Files.isDirectory(Paths.get(testDir + pathSep + dirName)));
azzertPerms(perms, dirName);
});
await();
}
private void testMkdir(String dirName, String perms, boolean createParents,
boolean shouldPass, Handler<Void> afterOK) throws Exception {
Handler<AsyncResult<Void>> handler = createHandler(shouldPass, afterOK);
if (createParents) {
if (perms != null) {
vertx.fileSystem().mkdirs(testDir + pathSep + dirName, perms, handler);
} else {
vertx.fileSystem().mkdirs(testDir + pathSep + dirName, handler);
}
} else {
if (perms != null) {
vertx.fileSystem().mkdir(testDir + pathSep + dirName, perms, handler);
} else {
vertx.fileSystem().mkdir(testDir + pathSep + dirName, handler);
}
}
}
@Test
public void testReadDirSimple() throws Exception {
String dirName = "some-dir";
mkDir(dirName);
int numFiles = 10;
for (int i = 0; i < numFiles; i++) {
createFileWithJunk(dirName + pathSep + "file-" + i + ".dat", 100);
}
testReadDir(dirName, null, true, fileNames -> {
assertEquals(numFiles, fileNames.size());
Set<String> fset = new HashSet<String>();
for (String fileName: fileNames) {
fset.add(fileName);
}
File dir = new File(testDir + pathSep + dirName);
String root;
try {
root = dir.getCanonicalPath();
} catch (IOException e) {
fail(e.getMessage());
return;
}
for (int i = 0; i < numFiles; i++) {
assertTrue(fset.contains(root + pathSep + "file-" + i + ".dat"));
}
});
await();
}
@Test
public void testReadDirWithFilter() throws Exception {
String dirName = "some-dir";
mkDir(dirName);
int numFiles = 10;
for (int i = 0; i < numFiles; i++) {
createFileWithJunk(dirName + pathSep + "foo-" + i + ".txt", 100);
}
for (int i = 0; i < numFiles; i++) {
createFileWithJunk(dirName + pathSep + "bar-" + i + ".txt", 100);
}
testReadDir(dirName, "foo.+", true, fileNames -> {
assertEquals(numFiles, fileNames.size());
Set<String> fset = new HashSet<>();
for (String fileName: fileNames) {
fset.add(fileName);
}
File dir = new File(testDir + pathSep + dirName);
String root;
try {
root = dir.getCanonicalPath();
} catch (IOException e) {
fail(e.getMessage());
return;
}
for (int i = 0; i < numFiles; i++) {
assertTrue(fset.contains(root + pathSep + "foo-" + i + ".txt"));
}
});
await();
}
private void testReadDir(String dirName, String filter, boolean shouldPass,
Handler<List<String>> afterOK) throws Exception {
Handler<AsyncResult<List<String>>> handler = ar -> {
if (ar.failed()) {
if (shouldPass) {
fail(ar.cause().getMessage());
} else {
assertTrue(ar.cause() instanceof FileSystemException);
if (afterOK != null) {
afterOK.handle(null);
}
testComplete();
}
} else {
if (shouldPass) {
if (afterOK != null) {
afterOK.handle(ar.result());
}
testComplete();
} else {
fail("read should fail");
}
}
};
if (filter == null) {
vertx.fileSystem().readDir(testDir + pathSep + dirName, handler);
} else {
vertx.fileSystem().readDir(testDir + pathSep + dirName, filter, handler);
}
}
@Test
public void testReadFile() throws Exception {
byte[] content = TestUtils.randomByteArray(1000);
String fileName = "some-file.dat";
createFile(fileName, content);
vertx.fileSystem().readFile(testDir + pathSep + fileName, ar -> {
if (ar.failed()) {
fail(ar.cause().getMessage());
} else {
assertEquals(Buffer.buffer(content), ar.result());
testComplete();
}
});
await();
}
@Test
public void testWriteFile() throws Exception {
byte[] content = TestUtils.randomByteArray(1000);
Buffer buff = Buffer.buffer(content);
String fileName = "some-file.dat";
vertx.fileSystem().writeFile(testDir + pathSep + fileName, buff, ar -> {
if (ar.failed()) {
fail(ar.cause().getMessage());
} else {
assertTrue(fileExists(fileName));
assertEquals(content.length, fileLength(fileName));
byte[] readBytes;
try {
readBytes = Files.readAllBytes(Paths.get(testDir + pathSep + fileName));
} catch (IOException e) {
fail(e.getMessage());
return;
}
assertEquals(buff, Buffer.buffer(readBytes));
testComplete();
}
});
await();
}
@Test
public void testWriteAsync() throws Exception {
String fileName = "some-file.dat";
int chunkSize = 1000;
int chunks = 10;
byte[] content = TestUtils.randomByteArray(chunkSize * chunks);
Buffer buff = Buffer.buffer(content);
AtomicInteger count = new AtomicInteger();
vertx.fileSystem().open(testDir + pathSep + fileName, new OpenOptions(), arr -> {
if (arr.succeeded()) {
for (int i = 0; i < chunks; i++) {
Buffer chunk = buff.getBuffer(i * chunkSize, (i + 1) * chunkSize);
assertEquals(chunkSize, chunk.length());
arr.result().write(chunk, i * chunkSize, ar -> {
if (ar.succeeded()) {
if (count.incrementAndGet() == chunks) {
arr.result().close(ar2 -> {
if (ar2.failed()) {
fail(ar2.cause().getMessage());
} else {
assertTrue(fileExists(fileName));
byte[] readBytes;
try {
readBytes = Files.readAllBytes(Paths.get(testDir + pathSep + fileName));
} catch (IOException e) {
fail(e.getMessage());
return;
}
Buffer read = Buffer.buffer(readBytes);
assertEquals(buff, read);
testComplete();
}
});
}
} else {
fail(ar.cause().getMessage());
}
});
}
} else {
fail(arr.cause().getMessage());
}
});
await();
}
@Test
public void testReadAsync() throws Exception {
String fileName = "some-file.dat";
int chunkSize = 1000;
int chunks = 10;
byte[] content = TestUtils.randomByteArray(chunkSize * chunks);
Buffer expected = Buffer.buffer(content);
createFile(fileName, content);
AtomicInteger reads = new AtomicInteger();
vertx.fileSystem().open(testDir + pathSep + fileName, new OpenOptions(), arr -> {
if (arr.succeeded()) {
Buffer buff = Buffer.buffer(chunks * chunkSize);
for (int i = 0; i < chunks; i++) {
arr.result().read(buff, i * chunkSize, i * chunkSize, chunkSize, arb -> {
if (arb.succeeded()) {
if (reads.incrementAndGet() == chunks) {
arr.result().close(ar -> {
if (ar.failed()) {
fail(ar.cause().getMessage());
} else {
assertEquals(expected, buff);
assertEquals(buff, arb.result());
testComplete();
}
});
}
} else {
fail(arb.cause().getMessage());
}
});
}
} else {
fail(arr.cause().getMessage());
}
});
await();
}
@Test
public void testWriteStream() throws Exception {
String fileName = "some-file.dat";
int chunkSize = 1000;
int chunks = 10;
byte[] content = TestUtils.randomByteArray(chunkSize * chunks);
Buffer buff = Buffer.buffer(content);
vertx.fileSystem().open(testDir + pathSep + fileName, new OpenOptions(), ar -> {
if (ar.succeeded()) {
WriteStream<Buffer> ws = ar.result();
ws.exceptionHandler(t -> fail(t.getMessage()));
for (int i = 0; i < chunks; i++) {
Buffer chunk = buff.getBuffer(i * chunkSize, (i + 1) * chunkSize);
assertEquals(chunkSize, chunk.length());
ws.write(chunk);
}
ar.result().close(ar2 -> {
if (ar2.failed()) {
fail(ar2.cause().getMessage());
} else {
assertTrue(fileExists(fileName));
byte[] readBytes;
try {
readBytes = Files.readAllBytes(Paths.get(testDir + pathSep + fileName));
} catch (IOException e) {
fail(e.getMessage());
return;
}
assertEquals(buff, Buffer.buffer(readBytes));
testComplete();
}
});
} else {
fail(ar.cause().getMessage());
}
});
await();
}
@Test
public void testWriteStreamAppend() throws Exception {
String fileName = "some-file.dat";
int chunkSize = 1000;
int chunks = 10;
byte[] existing = TestUtils.randomByteArray(1000);
createFile(fileName, existing);
byte[] content = TestUtils.randomByteArray(chunkSize * chunks);
Buffer buff = Buffer.buffer(content);
vertx.fileSystem().open(testDir + pathSep + fileName, new OpenOptions(), ar -> {
if (ar.succeeded()) {
AsyncFile ws = ar.result();
long size = vertx.fileSystem().propsBlocking(testDir + pathSep + fileName).size();
ws.setWritePos(size);
ws.exceptionHandler(t -> fail(t.getMessage()));
for (int i = 0; i < chunks; i++) {
Buffer chunk = buff.getBuffer(i * chunkSize, (i + 1) * chunkSize);
assertEquals(chunkSize, chunk.length());
ws.write(chunk);
}
ar.result().close(ar2 -> {
if (ar2.failed()) {
fail(ar2.cause().getMessage());
} else {
assertTrue(fileExists(fileName));
byte[] readBytes;
try {
readBytes = Files.readAllBytes(Paths.get(testDir + pathSep + fileName));
} catch (IOException e) {
fail(e.getMessage());
return;
}
assertEquals(Buffer.buffer(existing).appendBuffer(buff), Buffer.buffer(readBytes));
testComplete();
}
});
} else {
fail(ar.cause().getMessage());
}
});
await();
}
@Test
public void testWriteStreamWithCompositeBuffer() throws Exception {
String fileName = "some-file.dat";
int chunkSize = 1000;
int chunks = 10;
byte[] content1 = TestUtils.randomByteArray(chunkSize * (chunks / 2));
byte[] content2 = TestUtils.randomByteArray(chunkSize * (chunks / 2));
ByteBuf byteBuf = Unpooled.wrappedBuffer(content1, content2);
Buffer buff = Buffer.buffer(byteBuf);
vertx.fileSystem().open(testDir + pathSep + fileName, new OpenOptions(), ar -> {
if (ar.succeeded()) {
WriteStream<Buffer> ws = ar.result();
ws.exceptionHandler(t -> fail(t.getMessage()));
ws.write(buff);
ar.result().close(ar2 -> {
if (ar2.failed()) {
fail(ar2.cause().getMessage());
} else {
assertTrue(fileExists(fileName));
byte[] readBytes;
try {
readBytes = Files.readAllBytes(Paths.get(testDir + pathSep + fileName));
} catch (IOException e) {
fail(e.getMessage());
return;
}
assertEquals(buff, Buffer.buffer(readBytes));
byteBuf.release();
testComplete();
}
});
} else {
fail(ar.cause().getMessage());
}
});
await();
}
@Test
public void testReadStream() throws Exception {
String fileName = "some-file.dat";
int chunkSize = 1000;
int chunks = 10;
byte[] content = TestUtils.randomByteArray(chunkSize * chunks);
createFile(fileName, content);
vertx.fileSystem().open(testDir + pathSep + fileName, new OpenOptions(), ar -> {
if (ar.succeeded()) {
ReadStream<Buffer> rs = ar.result();
Buffer buff = Buffer.buffer();
rs.handler(buff::appendBuffer);
rs.exceptionHandler(t -> fail(t.getMessage()));
rs.endHandler(v -> {
ar.result().close(ar2 -> {
if (ar2.failed()) {
fail(ar2.cause().getMessage());
} else {
assertEquals(Buffer.buffer(content), buff);
testComplete();
}
});
});
} else {
fail(ar.cause().getMessage());
}
});
await();
}
@Test
public void testReadStreamWithBufferSize() throws Exception {
String fileName = "some-file.dat";
int chunkSize = 16384;
int chunks = 1;
byte[] content = TestUtils.randomByteArray(chunkSize * chunks);
createFile(fileName, content);
vertx.fileSystem().open(testDir + pathSep + fileName, new OpenOptions(), ar -> {
if (ar.succeeded()) {
AsyncFile rs = ar.result();
rs.setReadBufferSize(chunkSize);
Buffer buff = Buffer.buffer();
int[] callCount = {0};
rs.handler((buff1) -> {
buff.appendBuffer(buff1);
callCount[0]++;
});
rs.exceptionHandler(t -> fail(t.getMessage()));
rs.endHandler(v -> {
ar.result().close(ar2 -> {
if (ar2.failed()) {
fail(ar2.cause().getMessage());
} else {
assertEquals(1, callCount[0]);
assertEquals(Buffer.buffer(content), buff);
testComplete();
}
});
});
} else {
fail(ar.cause().getMessage());
}
});
await();
}
@Test
public void testReadStreamSetReadPos() throws Exception {
String fileName = "some-file.dat";
int chunkSize = 1000;
int chunks = 10;
byte[] content = TestUtils.randomByteArray(chunkSize * chunks);
createFile(fileName, content);
vertx.fileSystem().open(testDir + pathSep + fileName, new OpenOptions(), ar -> {
if (ar.succeeded()) {
AsyncFile rs = ar.result();
rs.setReadPos(chunkSize * chunks / 2);
Buffer buff = Buffer.buffer();
rs.handler(buff::appendBuffer);
rs.exceptionHandler(t -> fail(t.getMessage()));
rs.endHandler(v -> {
ar.result().close(ar2 -> {
if (ar2.failed()) {
fail(ar2.cause().getMessage());
} else {
assertEquals(chunkSize * chunks / 2, buff.length());
byte[] lastHalf = new byte[chunkSize * chunks / 2];
System.arraycopy(content, chunkSize * chunks / 2, lastHalf, 0, chunkSize * chunks / 2);
assertEquals(Buffer.buffer(lastHalf), buff);
testComplete();
}
});
});
} else {
fail(ar.cause().getMessage());
}
});
await();
}
@Test
@SuppressWarnings("unchecked")
public void testPumpFileStreams() throws Exception {
String fileName1 = "some-file.dat";
String fileName2 = "some-other-file.dat";
//Non integer multiple of buffer size
int fileSize = (int) (AsyncFileImpl.DEFAULT_READ_BUFFER_SIZE * 1000.3);
byte[] content = TestUtils.randomByteArray(fileSize);
createFile(fileName1, content);
vertx.fileSystem().open(testDir + pathSep + fileName1, new OpenOptions(), arr -> {
if (arr.succeeded()) {
ReadStream rs = arr.result();
//Open file for writing
vertx.fileSystem().open(testDir + pathSep + fileName2, new OpenOptions(), ar -> {
if (ar.succeeded()) {
WriteStream ws = ar.result();
Pump p = Pump.pump(rs, ws);
p.start();
rs.endHandler(v -> {
arr.result().close(car -> {
if (car.failed()) {
fail(ar.cause().getMessage());
} else {
ar.result().close(ar2 -> {
if (ar2.failed()) {
fail(ar2.cause().getMessage());
} else {
assertTrue(fileExists(fileName2));
byte[] readBytes;
try {
readBytes = Files.readAllBytes(Paths.get(testDir + pathSep + fileName2));
} catch (IOException e) {
fail(e.getMessage());
return;
}
assertEquals(Buffer.buffer(content), Buffer.buffer(readBytes));
testComplete();
}
});
}
});
});
} else {
fail(ar.cause().getMessage());
}
});
} else {
fail(arr.cause().getMessage());
}
});
await();
}
@Test
public void testCreateFileNoPerms() throws Exception {
testCreateFile(null, true);
}
@Test
public void testCreateFileWithPerms() throws Exception {
testCreateFile("rwx------", true);
}
@Test
public void testCreateFileAlreadyExists() throws Exception {
createFileWithJunk("some-file.dat", 100);
testCreateFile(null, false);
}
private void testCreateFile(String perms, boolean shouldPass) throws Exception {
String fileName = "some-file.dat";
Handler<AsyncResult<Void>> handler = ar -> {
if (ar.failed()) {
if (shouldPass) {
fail(ar.cause().getMessage());
} else {
assertTrue(ar.cause() instanceof FileSystemException);
testComplete();
}
} else {
if (shouldPass) {
assertTrue(fileExists(fileName));
assertEquals(0, fileLength(fileName));
if (perms != null) {
azzertPerms(perms, fileName);
}
testComplete();
} else {
fail("test should fail");
}
}
};
if (perms != null) {
vertx.fileSystem().createFile(testDir + pathSep + fileName, perms, handler);
} else {
vertx.fileSystem().createFile(testDir + pathSep + fileName, handler);
}
await();
}
@Test
public void testExists() throws Exception {
testExists(true);
}
@Test
public void testNotExists() throws Exception {
testExists(false);
}
private void testExists(boolean exists) throws Exception {
String fileName = "some-file.dat";
if (exists) {
createFileWithJunk(fileName, 100);
}
vertx.fileSystem().exists(testDir + pathSep + fileName, ar -> {
if (ar.succeeded()) {
if (exists) {
assertTrue(ar.result());
} else {
assertFalse(ar.result());
}
testComplete();
} else {
fail(ar.cause().getMessage());
}
});
await();
}
@Test
public void testFSProps() throws Exception {
String fileName = "some-file.txt";
createFileWithJunk(fileName, 1234);
testFSProps(fileName, props -> {
assertTrue(props.totalSpace() > 0);
assertTrue(props.unallocatedSpace() > 0);
assertTrue(props.usableSpace() > 0);
});
await();
}
private void testFSProps(String fileName,
Handler<FileSystemProps> afterOK) throws Exception {
vertx.fileSystem().fsProps(testDir + pathSep + fileName, ar -> {
if (ar.failed()) {
fail(ar.cause().getMessage());
} else {
afterOK.handle(ar.result());
testComplete();
}
});
}
@Test
public void testOpenOptions() {
OpenOptions opts = new OpenOptions();
assertNull(opts.getPerms());
String perms = "rwxrwxrwx";
assertEquals(opts, opts.setPerms(perms));
assertEquals(perms, opts.getPerms());
assertTrue(opts.isCreate());
assertEquals(opts, opts.setCreate(false));
assertFalse(opts.isCreate());
assertFalse(opts.isCreateNew());
assertEquals(opts, opts.setCreateNew(true));
assertTrue(opts.isCreateNew());
assertTrue(opts.isRead());
assertEquals(opts, opts.setRead(false));
assertFalse(opts.isRead());
assertTrue(opts.isWrite());
assertEquals(opts, opts.setWrite(false));
assertFalse(opts.isWrite());
assertFalse(opts.isDsync());
assertEquals(opts, opts.setDsync(true));
assertTrue(opts.isDsync());
assertFalse(opts.isSync());
assertEquals(opts, opts.setSync(true));
assertTrue(opts.isSync());
assertFalse(opts.isDeleteOnClose());
assertEquals(opts, opts.setDeleteOnClose(true));
assertTrue(opts.isDeleteOnClose());
assertFalse(opts.isTruncateExisting());
assertEquals(opts, opts.setTruncateExisting(true));
assertTrue(opts.isTruncateExisting());
assertFalse(opts.isSparse());
assertEquals(opts, opts.setSparse(true));
assertTrue(opts.isSparse());
}
@Test
public void testDefaultOptionOptions() {
OpenOptions def = new OpenOptions();
OpenOptions json = new OpenOptions(new JsonObject());
assertEquals(def.getPerms(), json.getPerms());
assertEquals(def.isRead(), json.isRead());
assertEquals(def.isWrite(), json.isWrite());
assertEquals(def.isCreate(), json.isCreate());
assertEquals(def.isCreateNew(), json.isCreateNew());
assertEquals(def.isDeleteOnClose(), json.isDeleteOnClose());
assertEquals(def.isTruncateExisting(), json.isTruncateExisting());
assertEquals(def.isSparse(), json.isSparse());
assertEquals(def.isSync(), json.isSync());
assertEquals(def.isDsync(), json.isDsync());
}
@Test
public void testAsyncFileCloseHandlerIsAsync() throws Exception {
String fileName = "some-file.dat";
createFileWithJunk(fileName, 100);
AsyncFile file = vertx.fileSystem().openBlocking(testDir + pathSep + fileName, new OpenOptions());
ThreadLocal stack = new ThreadLocal();
stack.set(true);
file.close(ar -> {
assertNull(stack.get());
assertTrue(Vertx.currentContext().isEventLoopContext());
testComplete();
});
await();
}
@Test
public void testDrainNotCalledAfterClose() throws Exception {
String fileName = "some-file.dat";
vertx.fileSystem().open(testDir + pathSep + fileName, new OpenOptions(), onSuccess(file -> {
Buffer buf = TestUtils.randomBuffer(1024 * 1024);
file.write(buf);
AtomicBoolean drainAfterClose = new AtomicBoolean();
file.drainHandler(v -> {
drainAfterClose.set(true);
});
file.close(ar -> {
assertFalse(drainAfterClose.get());
testComplete();
});
}));
await();
}
@Test
public void testResumeFileInEndHandler() throws Exception {
Buffer expected = TestUtils.randomBuffer(10000);
String fileName = "some-file.dat";
createFile(fileName, expected.getBytes());
vertx.fileSystem().open(testDir + pathSep + fileName, new OpenOptions(), onSuccess(file -> {
Buffer buffer = Buffer.buffer();
file.endHandler(v -> {
assertEquals(buffer.length(), expected.length());
file.pause();
file.resume();
complete();
});
file.handler(buffer::appendBuffer);
}));
await();
}
private Handler<AsyncResult<Void>> createHandler(boolean shouldPass, Handler<Void> afterOK) {
return ar -> {
if (ar.failed()) {
if (shouldPass) {
fail(ar.cause().getMessage());
} else {
assertTrue(ar.cause() instanceof FileSystemException);
if (afterOK != null) {
afterOK.handle(null);
}
testComplete();
}
} else {
if (shouldPass) {
if (afterOK != null) {
afterOK.handle(null);
}
testComplete();
} else {
fail("operation should fail");
}
}
};
}
// Helper methods
private boolean fileExists(String fileName) {
File file = new File(testDir, fileName);
return file.exists();
}
private void createFileWithJunk(String fileName, long length) throws Exception {
createFile(fileName, TestUtils.randomByteArray((int) length));
}
private void createFile(String fileName, byte[] bytes) throws Exception {
File file = new File(testDir, fileName);
Path path = Paths.get(file.getCanonicalPath());
Files.write(path, bytes);
setPerms( path, DEFAULT_FILE_PERMS );
}
private void deleteDir(File dir) {
File[] files = dir.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
deleteDir(files[i]);
} else {
files[i].delete();
}
}
dir.delete();
}
private void deleteDir(String dir) {
deleteDir(new File(testDir + pathSep + dir));
}
private void mkDir(String dirName) throws Exception {
File dir = new File(testDir + pathSep + dirName);
dir.mkdir();
setPerms( Paths.get( dir.getCanonicalPath() ), DEFAULT_DIR_PERMS );
}
private long fileLength(String fileName) {
File file = new File(testDir, fileName);
return file.length();
}
private void setPerms(Path path, String perms) {
if (Utils.isWindows() == false) {
try {
Files.setPosixFilePermissions( path, PosixFilePermissions.fromString(perms) );
}
catch(IOException e) {
throw new RuntimeException(e.getMessage());
}
}
}
private String getPerms(String fileName) {
try {
Set<PosixFilePermission> perms = Files.getPosixFilePermissions(Paths.get(testDir + pathSep + fileName));
return PosixFilePermissions.toString(perms);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
private void deleteFile(String fileName) {
File file = new File(testDir + pathSep + fileName);
file.delete();
}
}