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:
Markus Kreusch
2016-01-22 22:52:39 +01:00
parent cd72dae0d7
commit 6479573346
12 changed files with 317 additions and 139 deletions

View File

@@ -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;
}
}
};
}
}

View File

@@ -0,0 +1,8 @@
package org.cryptomator.common;
@FunctionalInterface
public interface RunnableThrowingException<T extends Exception> {
void run() throws T;
}

View File

@@ -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));
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}
};
}
}

View File

@@ -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;
}
}

View File

@@ -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");
}
}
}

View File

@@ -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() {

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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