mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-23 05:01:28 +00:00
Added FolderCopyToTests
* Tests for CopyTo Operation * Changes to Matchers and Test-Utilities * Changes to make things work * TODO: One test still not working due to access to channel by multiple threads
This commit is contained in:
@@ -37,4 +37,25 @@ public class OptionalMatcher {
|
||||
};
|
||||
}
|
||||
|
||||
public static <T> Matcher<Optional<T>> emptyOptional() {
|
||||
return new TypeSafeDiagnosingMatcher<Optional<T>>(Optional.class) {
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("an empty Optional");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchesSafely(Optional<T> item, Description mismatchDescription) {
|
||||
if (item.isPresent()) {
|
||||
mismatchDescription.appendText("a present Optional of ").appendValue(item.get());
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.cryptomator.common;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface RunnableThrowingException<T extends Exception> {
|
||||
|
||||
void run() throws T;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
package org.cryptomator.filesystem.invariants;
|
||||
|
||||
import static org.cryptomator.filesystem.invariants.matchers.NodeMatchers.hasContent;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assume.assumeThat;
|
||||
|
||||
import java.io.UncheckedIOException;
|
||||
|
||||
import org.cryptomator.filesystem.File;
|
||||
import org.cryptomator.filesystem.FileSystem;
|
||||
import org.cryptomator.filesystem.Folder;
|
||||
import org.cryptomator.filesystem.invariants.FileSystemFactories.FileSystemFactory;
|
||||
import org.cryptomator.filesystem.invariants.WaysToObtainAFile.WayToObtainAFile;
|
||||
import org.cryptomator.filesystem.invariants.WaysToObtainAFolder.WayToObtainAFolder;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.experimental.theories.DataPoints;
|
||||
import org.junit.experimental.theories.Theories;
|
||||
import org.junit.experimental.theories.Theory;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(Theories.class)
|
||||
public class FolderCopyToTests {
|
||||
|
||||
private static final String SOURCE_FOLDER_NAME = "sourceFolderName";
|
||||
private static final String TARGET_FOLDER_NAME = "targetFolderName";
|
||||
|
||||
@DataPoints
|
||||
public static final Iterable<FileSystemFactory> FILE_SYSTEM_FACTORIES = new FileSystemFactories();
|
||||
|
||||
@DataPoints
|
||||
public static final Iterable<WayToObtainAFolder> WAYS_TO_OBTAIN_A_FOLDER = new WaysToObtainAFolder();
|
||||
|
||||
@DataPoints
|
||||
public static final Iterable<WayToObtainAFile> WAYS_TO_OBTAIN_A_FILE = new WaysToObtainAFile();
|
||||
|
||||
@Rule
|
||||
public final ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Theory
|
||||
public void testCopyAnExistingFolderToANonExistingFolderCreatesTheTargetFolder(FileSystemFactory fileSystemFactory, WayToObtainAFolder wayToObtainAnExistingFolder, WayToObtainAFolder wayToObtainANonExistingFolder) {
|
||||
assumeThat(wayToObtainAnExistingFolder.returnedFoldersExist(), is(true));
|
||||
assumeThat(wayToObtainANonExistingFolder.returnedFoldersExist(), is(false));
|
||||
|
||||
FileSystem fileSystem = fileSystemFactory.create();
|
||||
|
||||
Folder source = wayToObtainAnExistingFolder.folderWithName(fileSystem, SOURCE_FOLDER_NAME);
|
||||
Folder target = wayToObtainANonExistingFolder.folderWithName(fileSystem, TARGET_FOLDER_NAME);
|
||||
|
||||
source.copyTo(target);
|
||||
|
||||
assertThat(source.exists(), is(true));
|
||||
assertThat(target.exists(), is(true));
|
||||
}
|
||||
|
||||
@Theory
|
||||
public void testCopyAnExistingFolderToANonExistingFolderWhooseParentDoesNotExistCreatesTheParentAndTargetFolder(FileSystemFactory fileSystemFactory, WayToObtainAFolder wayToObtainAnExistingFolder,
|
||||
WayToObtainAFolder wayToObtainANonExistingFolder) {
|
||||
assumeThat(wayToObtainAnExistingFolder.returnedFoldersExist(), is(true));
|
||||
assumeThat(wayToObtainANonExistingFolder.returnedFoldersExist(), is(false));
|
||||
|
||||
FileSystem fileSystem = fileSystemFactory.create();
|
||||
|
||||
Folder source = wayToObtainAnExistingFolder.folderWithName(fileSystem, SOURCE_FOLDER_NAME);
|
||||
Folder parentOfTarget = wayToObtainANonExistingFolder.folderWithName(fileSystem, TARGET_FOLDER_NAME);
|
||||
Folder target = wayToObtainANonExistingFolder.folderWithName(parentOfTarget, TARGET_FOLDER_NAME);
|
||||
|
||||
source.copyTo(target);
|
||||
|
||||
assertThat(source.exists(), is(true));
|
||||
assertThat(parentOfTarget.exists(), is(true));
|
||||
assertThat(target.exists(), is(true));
|
||||
}
|
||||
|
||||
@Theory
|
||||
public void testCopyANonExistingFolderFails(FileSystemFactory fileSystemFactory, WayToObtainAFolder wayToObtainANonExistingFolder) {
|
||||
assumeThat(wayToObtainANonExistingFolder.returnedFoldersExist(), is(false));
|
||||
|
||||
FileSystem fileSystem = fileSystemFactory.create();
|
||||
|
||||
Folder source = wayToObtainANonExistingFolder.folderWithName(fileSystem, SOURCE_FOLDER_NAME);
|
||||
Folder target = wayToObtainANonExistingFolder.folderWithName(fileSystem, TARGET_FOLDER_NAME);
|
||||
|
||||
thrown.expect(UncheckedIOException.class);
|
||||
|
||||
source.copyTo(target);
|
||||
}
|
||||
|
||||
@Theory
|
||||
public void testCopyAnExistingFolderToAnExistingFolderSucceeds(FileSystemFactory fileSystemFactory, WayToObtainAFolder wayToObtainAnExistingFolder) {
|
||||
assumeThat(wayToObtainAnExistingFolder.returnedFoldersExist(), is(true));
|
||||
|
||||
FileSystem fileSystem = fileSystemFactory.create();
|
||||
|
||||
Folder source = wayToObtainAnExistingFolder.folderWithName(fileSystem, SOURCE_FOLDER_NAME);
|
||||
Folder target = wayToObtainAnExistingFolder.folderWithName(fileSystem, TARGET_FOLDER_NAME);
|
||||
|
||||
source.copyTo(target);
|
||||
|
||||
assertThat(source.exists(), is(true));
|
||||
assertThat(target.exists(), is(true));
|
||||
}
|
||||
|
||||
@Theory
|
||||
@Ignore
|
||||
// FIXME not working yet due to concurrent access to and interruption of channel
|
||||
public void testCopyAFolderWithChildrenCopiesChildrenRecursive(FileSystemFactory fileSystemFactory, WayToObtainAFolder wayToObtainAnExistingFolder, WayToObtainAFile wayToObtainAnExisitingFile,
|
||||
WayToObtainAFolder wayToObtainANonExistingFolder) {
|
||||
|
||||
assumeThat(wayToObtainAnExistingFolder.returnedFoldersExist(), is(true));
|
||||
assumeThat(wayToObtainANonExistingFolder.returnedFoldersExist(), is(false));
|
||||
assumeThat(wayToObtainAnExisitingFile.returnedFilesExist(), is(true));
|
||||
|
||||
String childFolderName = "childFolderName";
|
||||
String childFileName = "childFileName";
|
||||
String childFoldersChildFileName = "childFoldersChildFile";
|
||||
byte[] content1 = {23, 127, 3, 10, 101};
|
||||
byte[] content2 = {43, 22, 103, 67, 51, 5, 15, 93, 33};
|
||||
FileSystem fileSystem = fileSystemFactory.create();
|
||||
|
||||
Folder source = wayToObtainAnExistingFolder.folderWithName(fileSystem, SOURCE_FOLDER_NAME);
|
||||
Folder childFolder = wayToObtainAnExistingFolder.folderWithName(source, childFolderName);
|
||||
File childFile = wayToObtainAnExisitingFile.fileWithNameAndContent(source, childFileName, content1);
|
||||
File childFoldersChildFile = wayToObtainAnExisitingFile.fileWithNameAndContent(childFolder, childFoldersChildFileName, content2);
|
||||
|
||||
Folder target = wayToObtainANonExistingFolder.folderWithName(fileSystem, TARGET_FOLDER_NAME);
|
||||
Folder targetChildFolder = target.folder(childFolderName);
|
||||
File targetChildFile = target.file(childFileName);
|
||||
File targetChildFoldersChildFile = targetChildFolder.file(childFoldersChildFileName);
|
||||
|
||||
source.copyTo(target);
|
||||
|
||||
assertThat(source.exists(), is(true));
|
||||
assertThat(childFolder.exists(), is(true));
|
||||
assertThat(childFile.exists(), is(true));
|
||||
assertThat(childFoldersChildFile.exists(), is(true));
|
||||
|
||||
assertThat(target.exists(), is(true));
|
||||
assertThat(targetChildFolder.exists(), is(true));
|
||||
assertThat(targetChildFile, hasContent(content1));
|
||||
assertThat(targetChildFoldersChildFile, hasContent(content2));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,17 +17,17 @@ class WaysToObtainAFile implements Iterable<WayToObtainAFile> {
|
||||
public WaysToObtainAFile() {
|
||||
addNonExisting("invoke file", this::invokeFile);
|
||||
|
||||
addExisting("create file by writing to it", this::createFileUsingTouch);
|
||||
addExisting("create file by writing to it", this::createFileByWritingToIt);
|
||||
}
|
||||
|
||||
private File invokeFile(Folder parent, String name) {
|
||||
private File invokeFile(Folder parent, String name, byte[] content) {
|
||||
return parent.file(name);
|
||||
}
|
||||
|
||||
private File createFileUsingTouch(Folder parent, String name) {
|
||||
private File createFileByWritingToIt(Folder parent, String name, byte[] content) {
|
||||
File result = parent.file(name);
|
||||
try (WritableFile writable = result.openWritable()) {
|
||||
writable.write(ByteBuffer.wrap(new byte[] {1}));
|
||||
writable.write(ByteBuffer.wrap(content));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -35,8 +35,8 @@ class WaysToObtainAFile implements Iterable<WayToObtainAFile> {
|
||||
private void addExisting(String name, WayToObtainAFileThatExists factory) {
|
||||
values.add(new WayToObtainAFileThatExists() {
|
||||
@Override
|
||||
public File fileWithName(Folder parent, String name) {
|
||||
return factory.fileWithName(parent, name);
|
||||
public File fileWithNameAndContent(Folder parent, String name, byte[] content) {
|
||||
return factory.fileWithNameAndContent(parent, name, content);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -49,8 +49,8 @@ class WaysToObtainAFile implements Iterable<WayToObtainAFile> {
|
||||
private void addNonExisting(String name, WayToObtainAFileThatDoesntExist factory) {
|
||||
values.add(new WayToObtainAFileThatDoesntExist() {
|
||||
@Override
|
||||
public File fileWithName(Folder parent, String name) {
|
||||
return factory.fileWithName(parent, name);
|
||||
public File fileWithNameAndContent(Folder parent, String name, byte[] content) {
|
||||
return factory.fileWithNameAndContent(parent, name, content);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,20 +62,24 @@ class WaysToObtainAFile implements Iterable<WayToObtainAFile> {
|
||||
|
||||
public interface WayToObtainAFile {
|
||||
|
||||
File fileWithName(Folder parent, String name);
|
||||
default File fileWithName(Folder parent, String name) {
|
||||
return fileWithNameAndContent(parent, name, new byte[0]);
|
||||
}
|
||||
|
||||
File fileWithNameAndContent(Folder parent, String name, byte[] content);
|
||||
|
||||
boolean returnedFilesExist();
|
||||
|
||||
}
|
||||
|
||||
public interface WayToObtainAFileThatExists extends WayToObtainAFile {
|
||||
private interface WayToObtainAFileThatExists extends WayToObtainAFile {
|
||||
@Override
|
||||
default boolean returnedFilesExist() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public interface WayToObtainAFileThatDoesntExist extends WayToObtainAFile {
|
||||
private interface WayToObtainAFileThatDoesntExist extends WayToObtainAFile {
|
||||
@Override
|
||||
default boolean returnedFilesExist() {
|
||||
return false;
|
||||
|
||||
@@ -100,14 +100,14 @@ class WaysToObtainAFolder implements Iterable<WayToObtainAFolder> {
|
||||
|
||||
}
|
||||
|
||||
public interface WayToObtainAFolderThatExists extends WayToObtainAFolder {
|
||||
private interface WayToObtainAFolderThatExists extends WayToObtainAFolder {
|
||||
@Override
|
||||
default boolean returnedFoldersExist() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public interface WayToObtainAFolderThatDoesntExists extends WayToObtainAFolder {
|
||||
private interface WayToObtainAFolderThatDoesntExists extends WayToObtainAFolder {
|
||||
@Override
|
||||
default boolean returnedFoldersExist() {
|
||||
return false;
|
||||
|
||||
@@ -2,9 +2,13 @@ package org.cryptomator.filesystem.invariants.matchers;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.cryptomator.common.test.matcher.PropertyMatcher;
|
||||
import org.cryptomator.filesystem.File;
|
||||
import org.cryptomator.filesystem.Folder;
|
||||
import org.cryptomator.filesystem.ReadableFile;
|
||||
import org.hamcrest.Matcher;
|
||||
|
||||
public class NodeMatchers {
|
||||
@@ -17,4 +21,24 @@ public class NodeMatchers {
|
||||
return new PropertyMatcher<>(File.class, File::name, "name", is(name));
|
||||
}
|
||||
|
||||
public static Matcher<File> hasContent(byte[] content) {
|
||||
return new PropertyMatcher<>(File.class, readFileContentWithLength(content.length), "content", is(content));
|
||||
}
|
||||
|
||||
private static Function<File, byte[]> readFileContentWithLength(int expectedLength) {
|
||||
return file -> {
|
||||
try (ReadableFile readable = file.openReadable()) {
|
||||
ByteBuffer buffer = ByteBuffer.allocate(expectedLength + 1);
|
||||
readable.read(buffer);
|
||||
if (buffer.remaining() == 0) {
|
||||
throw new IllegalStateException("File content > expectedLength of " + expectedLength);
|
||||
}
|
||||
buffer.flip();
|
||||
byte[] result = new byte[buffer.limit()];
|
||||
buffer.get(result);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.cryptomator.filesystem.nio;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
class OpenCloseCounter {
|
||||
|
||||
private final AtomicInteger counter = new AtomicInteger();
|
||||
|
||||
public void countOpen() {
|
||||
counter.incrementAndGet();
|
||||
}
|
||||
|
||||
public void countClose() {
|
||||
int openCount = counter.decrementAndGet();
|
||||
if (openCount < 0) {
|
||||
counter.incrementAndGet();
|
||||
throw new IllegalStateException("Close without corresponding open");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isOpen() {
|
||||
return counter.get() > 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,8 +9,6 @@ import java.nio.channels.FileChannel;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
@@ -20,8 +18,8 @@ class SharedFileChannel {
|
||||
|
||||
private final Path path;
|
||||
private final NioAccess nioAccess;
|
||||
private final OpenCloseCounter openCloseCounter;
|
||||
|
||||
private Map<Thread, Thread> openedBy = new ConcurrentHashMap<>();
|
||||
private Lock lock = new ReentrantLock();
|
||||
|
||||
private FileChannel delegate;
|
||||
@@ -29,66 +27,41 @@ class SharedFileChannel {
|
||||
public SharedFileChannel(Path path, NioAccess nioAccess) {
|
||||
this.path = path;
|
||||
this.nioAccess = nioAccess;
|
||||
}
|
||||
|
||||
public void openIfClosed(OpenMode mode) {
|
||||
if (!openedBy.containsKey(Thread.currentThread())) {
|
||||
open(mode);
|
||||
}
|
||||
this.openCloseCounter = new OpenCloseCounter();
|
||||
}
|
||||
|
||||
public void open(OpenMode mode) {
|
||||
doLocked(() -> {
|
||||
Thread thread = Thread.currentThread();
|
||||
boolean failed = true;
|
||||
try {
|
||||
if (openedBy.put(thread, thread) != null) {
|
||||
throw new IllegalStateException("SharedFileChannel already open for current thread");
|
||||
}
|
||||
openCloseCounter.countOpen();
|
||||
if (delegate == null) {
|
||||
createChannel(mode);
|
||||
}
|
||||
failed = false;
|
||||
} finally {
|
||||
if (failed) {
|
||||
openedBy.remove(thread);
|
||||
openCloseCounter.countClose();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void closeIfOpen() {
|
||||
if (openedBy.containsKey(Thread.currentThread())) {
|
||||
internalClose();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
assertOpenedByCurrentThread();
|
||||
internalClose();
|
||||
}
|
||||
|
||||
private void internalClose() {
|
||||
doLocked(() -> {
|
||||
openedBy.remove(Thread.currentThread());
|
||||
openCloseCounter.countClose();
|
||||
try {
|
||||
delegate.force(true);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
} finally {
|
||||
if (openedBy.isEmpty()) {
|
||||
if (!openCloseCounter.isOpen()) {
|
||||
closeChannel();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void assertOpenedByCurrentThread() {
|
||||
if (!openedBy.containsKey(Thread.currentThread())) {
|
||||
throw new IllegalStateException("SharedFileChannel closed for current thread");
|
||||
}
|
||||
}
|
||||
|
||||
private void createChannel(OpenMode mode) {
|
||||
try {
|
||||
if (nioAccess.isDirectory(path)) {
|
||||
@@ -116,7 +89,7 @@ class SharedFileChannel {
|
||||
}
|
||||
|
||||
public int readFully(long position, ByteBuffer target) {
|
||||
assertOpenedByCurrentThread();
|
||||
assertOpen();
|
||||
try {
|
||||
return tryReadFully(position, target);
|
||||
} catch (IOException e) {
|
||||
@@ -140,7 +113,7 @@ class SharedFileChannel {
|
||||
}
|
||||
|
||||
public void truncate(int i) {
|
||||
assertOpenedByCurrentThread();
|
||||
assertOpen();
|
||||
try {
|
||||
delegate.truncate(i);
|
||||
} catch (IOException e) {
|
||||
@@ -149,7 +122,7 @@ class SharedFileChannel {
|
||||
}
|
||||
|
||||
public long size() {
|
||||
assertOpenedByCurrentThread();
|
||||
assertOpen();
|
||||
try {
|
||||
return delegate.size();
|
||||
} catch (IOException e) {
|
||||
@@ -158,8 +131,8 @@ class SharedFileChannel {
|
||||
}
|
||||
|
||||
public long transferTo(long position, long count, SharedFileChannel targetChannel, long targetPosition) {
|
||||
assertOpenedByCurrentThread();
|
||||
targetChannel.assertOpenedByCurrentThread();
|
||||
assertOpen();
|
||||
targetChannel.assertOpen();
|
||||
if (count < 0) {
|
||||
throw new IllegalArgumentException("Count must not be negative");
|
||||
}
|
||||
@@ -187,7 +160,7 @@ class SharedFileChannel {
|
||||
}
|
||||
|
||||
public int writeFully(long position, ByteBuffer source) {
|
||||
assertOpenedByCurrentThread();
|
||||
assertOpen();
|
||||
try {
|
||||
return tryWriteFully(position, source);
|
||||
} catch (IOException e) {
|
||||
@@ -204,4 +177,10 @@ class SharedFileChannel {
|
||||
return count;
|
||||
}
|
||||
|
||||
private void assertOpen() {
|
||||
if (!openCloseCounter.isOpen()) {
|
||||
throw new IllegalStateException("SharedFileChannel is not open");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ class WritableNioFile implements WritableFile {
|
||||
private Runnable afterCloseCallback;
|
||||
|
||||
private boolean open = true;
|
||||
private boolean channelOpened = false;
|
||||
private long position = 0;
|
||||
|
||||
public WritableNioFile(FileSystem fileSystem, Path path, SharedFileChannel channel, Runnable afterCloseCallback, NioAccess nioAccess) {
|
||||
@@ -153,11 +154,16 @@ class WritableNioFile implements WritableFile {
|
||||
}
|
||||
|
||||
void ensureChannelIsOpened() {
|
||||
channel.openIfClosed(WRITE);
|
||||
if (!channelOpened) {
|
||||
channel.open(WRITE);
|
||||
channelOpened = true;
|
||||
}
|
||||
}
|
||||
|
||||
void closeChannelIfOpened() {
|
||||
channel.closeIfOpen();
|
||||
if (channelOpened) {
|
||||
channel.close();
|
||||
}
|
||||
}
|
||||
|
||||
FileSystem fileSystem() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.cryptomator.filesystem.nio;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static org.cryptomator.common.test.matcher.OptionalMatcher.emptyOptional;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Matchers.any;
|
||||
@@ -299,7 +300,7 @@ public class NioFileTest {
|
||||
|
||||
@Test
|
||||
public void testCreationTimeDelegatesToNioAccessCreationTime() throws IOException {
|
||||
Instant exectedResult = Instant.parse("2016-01-08T19:49:00Z");
|
||||
Instant exectedResult = Instant.parse("1970-01-02T00:00:00Z");
|
||||
when(nioAccess.getCreationTime(path)).thenReturn(FileTime.from(exectedResult));
|
||||
when(nioAccess.exists(path)).thenReturn(true);
|
||||
when(nioAccess.isRegularFile(path)).thenReturn(true);
|
||||
@@ -309,6 +310,15 @@ public class NioFileTest {
|
||||
assertThat(result, is(exectedResult));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreationTimeReturnsEmptyOptionalIfNioAccessCreationTimeReturnsValueBeforeJanuaryTheSecondNineteenhundredSeventy() throws IOException {
|
||||
when(nioAccess.getCreationTime(path)).thenReturn(FileTime.from(Instant.parse("1970-01-01T23:59:59Z")));
|
||||
when(nioAccess.exists(path)).thenReturn(true);
|
||||
when(nioAccess.isRegularFile(path)).thenReturn(true);
|
||||
|
||||
assertThat(inTest.creationTime(), is(emptyOptional()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreationTimeWrapsIOExceptionFromNioAccessCreationTimeInUncheckedIOException() throws IOException {
|
||||
IOException exceptionFromCreationTime = new IOException();
|
||||
|
||||
@@ -85,16 +85,6 @@ public class SharedFileChannelTest {
|
||||
verify(nioAccess).open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenIfClosedOpensAChannelIfChannelIsNotOpenOpenModeIsReadAndFileExists() throws IOException {
|
||||
when(nioAccess.isDirectory(path)).thenReturn(false);
|
||||
when(nioAccess.isRegularFile(path)).thenReturn(true);
|
||||
|
||||
inTest.openIfClosed(OpenMode.READ);
|
||||
|
||||
verify(nioAccess).open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenOpensAChannelIfOpenModeIsWriteAndFileExists() throws IOException {
|
||||
when(nioAccess.isDirectory(path)).thenReturn(false);
|
||||
@@ -128,41 +118,6 @@ public class SharedFileChannelTest {
|
||||
inTest.open(OpenMode.WRITE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenFailsIfInvokedTwiceBeforeClose() {
|
||||
when(nioAccess.isDirectory(path)).thenReturn(false);
|
||||
when(nioAccess.isRegularFile(path)).thenReturn(false);
|
||||
|
||||
inTest.open(OpenMode.WRITE);
|
||||
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("already open for current thread");
|
||||
|
||||
inTest.open(OpenMode.WRITE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenIfClosedDoesDoNothingIfInvokedOnOpenChannel() {
|
||||
when(nioAccess.isDirectory(path)).thenReturn(false);
|
||||
when(nioAccess.isRegularFile(path)).thenReturn(false);
|
||||
|
||||
inTest.open(OpenMode.WRITE);
|
||||
|
||||
inTest.openIfClosed(OpenMode.READ);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenWorksIfInvokedTwiceAfterClose() throws IOException {
|
||||
when(nioAccess.isDirectory(path)).thenReturn(false);
|
||||
when(nioAccess.isRegularFile(path)).thenReturn(false);
|
||||
when(nioAccess.open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)).thenReturn(mock(FileChannel.class));
|
||||
|
||||
inTest.open(OpenMode.WRITE);
|
||||
inTest.close();
|
||||
|
||||
inTest.open(OpenMode.WRITE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenDoesNotOpenChannelTwiceIfInvokedTwiceByDifferentThreads() throws IOException {
|
||||
when(nioAccess.isDirectory(path)).thenReturn(false);
|
||||
@@ -182,16 +137,11 @@ public class SharedFileChannelTest {
|
||||
@Test
|
||||
public void testCloseIfNotOpenFails() {
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("closed for current thread");
|
||||
thrown.expectMessage("Close without corresponding open");
|
||||
|
||||
inTest.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseIfOpenDoesNothingIfNotOpen() {
|
||||
inTest.closeIfOpen();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseIfClosedFails() throws IOException {
|
||||
when(nioAccess.isDirectory(path)).thenReturn(false);
|
||||
@@ -201,7 +151,7 @@ public class SharedFileChannelTest {
|
||||
inTest.close();
|
||||
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("closed for current thread");
|
||||
thrown.expectMessage("Close without corresponding open");
|
||||
|
||||
inTest.close();
|
||||
}
|
||||
@@ -257,19 +207,6 @@ public class SharedFileChannelTest {
|
||||
inTest.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseIfOpenClosesChannelIfOpen() throws IOException {
|
||||
when(nioAccess.isDirectory(path)).thenReturn(false);
|
||||
when(nioAccess.isRegularFile(path)).thenReturn(false);
|
||||
FileChannel channel = mock(FileChannel.class);
|
||||
when(nioAccess.open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)).thenReturn(channel);
|
||||
inTest.open(OpenMode.WRITE);
|
||||
|
||||
inTest.closeIfOpen();
|
||||
|
||||
verify(nioAccess).close(channel);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseDoesNotCloseChannelIfOpenedTwice() throws IOException {
|
||||
when(nioAccess.isDirectory(path)).thenReturn(false);
|
||||
@@ -686,7 +623,7 @@ public class SharedFileChannelTest {
|
||||
ByteBuffer irrelevant = null;
|
||||
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("closed for current thread");
|
||||
thrown.expectMessage("SharedFileChannel is not open");
|
||||
|
||||
inTest.readFully(0, irrelevant);
|
||||
}
|
||||
@@ -694,7 +631,7 @@ public class SharedFileChannelTest {
|
||||
@Test
|
||||
public void testTruncateFailsIfNotOpen() {
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("closed for current thread");
|
||||
thrown.expectMessage("SharedFileChannel is not open");
|
||||
|
||||
inTest.truncate(0);
|
||||
}
|
||||
@@ -702,7 +639,7 @@ public class SharedFileChannelTest {
|
||||
@Test
|
||||
public void testSizeFailsIfNotOpen() {
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("closed for current thread");
|
||||
thrown.expectMessage("SharedFileChannel is not open");
|
||||
|
||||
inTest.size();
|
||||
}
|
||||
@@ -712,7 +649,7 @@ public class SharedFileChannelTest {
|
||||
SharedFileChannel irrelevant = null;
|
||||
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("closed for current thread");
|
||||
thrown.expectMessage("SharedFileChannel is not open");
|
||||
|
||||
inTest.transferTo(0, 0, irrelevant, 0);
|
||||
}
|
||||
@@ -724,7 +661,7 @@ public class SharedFileChannelTest {
|
||||
inTest.open(OpenMode.WRITE);
|
||||
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("closed for current thread");
|
||||
thrown.expectMessage("SharedFileChannel is not open");
|
||||
|
||||
inTest.transferTo(0, 0, targetInTest, 0);
|
||||
}
|
||||
@@ -734,7 +671,7 @@ public class SharedFileChannelTest {
|
||||
ByteBuffer irrelevant = null;
|
||||
|
||||
thrown.expect(IllegalStateException.class);
|
||||
thrown.expectMessage("closed for current thread");
|
||||
thrown.expectMessage("SharedFileChannel is not open");
|
||||
|
||||
inTest.writeFully(0, irrelevant);
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ public class WritableNioFileTest {
|
||||
inTest.write(irrelevant);
|
||||
|
||||
InOrder inOrder = inOrder(channel);
|
||||
inOrder.verify(channel).openIfClosed(WRITE);
|
||||
inOrder.verify(channel).open(WRITE);
|
||||
inOrder.verify(channel).writeFully(0, irrelevant);
|
||||
}
|
||||
|
||||
@@ -217,11 +217,12 @@ public class WritableNioFileTest {
|
||||
when(nioAccess.isDirectory(path)).thenReturn(false);
|
||||
when(nioAccess.isDirectory(pathOfTarget)).thenReturn(false);
|
||||
|
||||
inTest.ensureChannelIsOpened();
|
||||
inTest.moveTo(target);
|
||||
|
||||
InOrder inOrder = inOrder(target, nioAccess, channel, afterCloseCallback);
|
||||
inOrder.verify(target).assertOpen();
|
||||
inOrder.verify(channel).closeIfOpen();
|
||||
inOrder.verify(channel).close();
|
||||
inOrder.verify(target).closeChannelIfOpened();
|
||||
inOrder.verify(nioAccess).move(path, pathOfTarget, REPLACE_EXISTING);
|
||||
inOrder.verify(target).invokeAfterCloseCallback();
|
||||
@@ -269,7 +270,7 @@ public class WritableNioFileTest {
|
||||
inTest.setLastModified(instant);
|
||||
|
||||
InOrder inOrder = inOrder(channel, nioAccess);
|
||||
inOrder.verify(channel).openIfClosed(OpenMode.WRITE);
|
||||
inOrder.verify(channel).open(OpenMode.WRITE);
|
||||
inOrder.verify(nioAccess).setLastModifiedTime(path, time);
|
||||
}
|
||||
|
||||
@@ -308,7 +309,7 @@ public class WritableNioFileTest {
|
||||
inTest.setCreationTime(instant);
|
||||
|
||||
InOrder inOrder = inOrder(nioAccess, channel);
|
||||
inOrder.verify(channel).openIfClosed(OpenMode.WRITE);
|
||||
inOrder.verify(channel).open(OpenMode.WRITE);
|
||||
inOrder.verify(nioAccess).setCreationTime(path, FileTime.from(instant));
|
||||
}
|
||||
|
||||
@@ -330,10 +331,11 @@ public class WritableNioFileTest {
|
||||
|
||||
@Test
|
||||
public void testDeleteClosesChannelIfOpenAndDeletesFileAndInvokesAfterCloseCallback() throws IOException {
|
||||
inTest.ensureChannelIsOpened();
|
||||
inTest.delete();
|
||||
|
||||
InOrder inOrder = inOrder(channel, nioAccess, afterCloseCallback);
|
||||
inOrder.verify(channel).closeIfOpen();
|
||||
inOrder.verify(channel).close();
|
||||
inOrder.verify(nioAccess).delete(path);
|
||||
inOrder.verify(afterCloseCallback).run();
|
||||
}
|
||||
@@ -384,7 +386,7 @@ public class WritableNioFileTest {
|
||||
inTest.truncate();
|
||||
|
||||
InOrder inOrder = inOrder(channel);
|
||||
inOrder.verify(channel).openIfClosed(WRITE);
|
||||
inOrder.verify(channel).open(WRITE);
|
||||
inOrder.verify(channel).truncate(anyInt());
|
||||
}
|
||||
|
||||
@@ -406,7 +408,7 @@ public class WritableNioFileTest {
|
||||
inTest.close();
|
||||
|
||||
InOrder inOrder = inOrder(channel, afterCloseCallback);
|
||||
inOrder.verify(channel).closeIfOpen();
|
||||
inOrder.verify(channel).close();
|
||||
inOrder.verify(afterCloseCallback).run();
|
||||
}
|
||||
|
||||
@@ -418,7 +420,7 @@ public class WritableNioFileTest {
|
||||
inTest.close();
|
||||
|
||||
InOrder inOrder = inOrder(channel, afterCloseCallback);
|
||||
inOrder.verify(channel).closeIfOpen();
|
||||
inOrder.verify(channel).close();
|
||||
verify(afterCloseCallback).run();
|
||||
}
|
||||
|
||||
@@ -426,7 +428,7 @@ public class WritableNioFileTest {
|
||||
public void testCloseInvokesAfterCloseCallbackEvenIfCloseThrowsException() {
|
||||
inTest.truncate();
|
||||
String message = "exceptionMessage";
|
||||
doThrow(new RuntimeException(message)).when(channel).closeIfOpen();
|
||||
doThrow(new RuntimeException(message)).when(channel).close();
|
||||
|
||||
thrown.expectMessage(message);
|
||||
|
||||
@@ -522,17 +524,33 @@ public class WritableNioFileTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnsureChannelIsOpenedInvokesChannelOpenIfClosedWithModeWrite() {
|
||||
public void testEnsureChannelIsOpenedInvokesChannelOpenWithModeWrite() {
|
||||
inTest.ensureChannelIsOpened();
|
||||
|
||||
verify(channel).openIfClosed(WRITE);
|
||||
verify(channel).open(WRITE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseChannelIfOpenInvokesChannelsCloseIfOpen() {
|
||||
public void testEnsureChannelIsOpenedInvokesChannelOpenWithModeWriteOnlyOnceIfInvokedTwice() {
|
||||
inTest.ensureChannelIsOpened();
|
||||
inTest.ensureChannelIsOpened();
|
||||
|
||||
verify(channel).open(WRITE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseChannelIfOpenInvokesChannelsCloseIfOpenedEarlier() {
|
||||
inTest.ensureChannelIsOpened();
|
||||
inTest.closeChannelIfOpened();
|
||||
|
||||
verify(channel).closeIfOpen();
|
||||
verify(channel).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseChannelIfOpenDoesNotInvokeChannelsCloseIfNotOpenedEarlier() {
|
||||
inTest.closeChannelIfOpened();
|
||||
|
||||
verifyZeroInteractions(channel);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user