|
|
|
|
@@ -1,11 +1,11 @@
|
|
|
|
|
package org.cryptomator.filesystem.nio;
|
|
|
|
|
|
|
|
|
|
import static java.lang.String.format;
|
|
|
|
|
import static org.apache.commons.lang3.concurrent.ConcurrentUtils.constantFuture;
|
|
|
|
|
import static org.cryptomator.filesystem.nio.SharedFileChannel.EOF;
|
|
|
|
|
import static org.hamcrest.CoreMatchers.instanceOf;
|
|
|
|
|
import static org.hamcrest.CoreMatchers.is;
|
|
|
|
|
import static org.junit.Assert.assertThat;
|
|
|
|
|
import static org.mockito.Matchers.any;
|
|
|
|
|
import static org.mockito.Matchers.anyLong;
|
|
|
|
|
import static org.mockito.Mockito.doThrow;
|
|
|
|
|
import static org.mockito.Mockito.inOrder;
|
|
|
|
|
import static org.mockito.Mockito.mock;
|
|
|
|
|
@@ -17,9 +17,11 @@ import static org.mockito.Mockito.when;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.io.UncheckedIOException;
|
|
|
|
|
import java.nio.ByteBuffer;
|
|
|
|
|
import java.nio.channels.FileChannel;
|
|
|
|
|
import java.nio.channels.AsynchronousFileChannel;
|
|
|
|
|
import java.nio.file.Path;
|
|
|
|
|
import java.nio.file.StandardOpenOption;
|
|
|
|
|
import java.util.concurrent.ExecutionException;
|
|
|
|
|
import java.util.concurrent.Future;
|
|
|
|
|
|
|
|
|
|
import org.cryptomator.common.Holder;
|
|
|
|
|
import org.junit.Before;
|
|
|
|
|
@@ -122,7 +124,7 @@ public class SharedFileChannelTest {
|
|
|
|
|
public void testOpenDoesNotOpenChannelTwiceIfInvokedTwiceByDifferentThreads() 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));
|
|
|
|
|
when(nioAccess.open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)).thenReturn(mock(AsynchronousFileChannel.class));
|
|
|
|
|
|
|
|
|
|
inThreadRethrowingException(() -> inTest.open(OpenMode.WRITE));
|
|
|
|
|
inThreadRethrowingException(() -> inTest.open(OpenMode.WRITE));
|
|
|
|
|
@@ -146,7 +148,7 @@ public class SharedFileChannelTest {
|
|
|
|
|
public void testCloseIfClosedFails() 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));
|
|
|
|
|
when(nioAccess.open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)).thenReturn(mock(AsynchronousFileChannel.class));
|
|
|
|
|
inTest.open(OpenMode.WRITE);
|
|
|
|
|
inTest.close();
|
|
|
|
|
|
|
|
|
|
@@ -160,7 +162,7 @@ public class SharedFileChannelTest {
|
|
|
|
|
public void testCloseForcesAndClosesChannel() throws IOException {
|
|
|
|
|
when(nioAccess.isDirectory(path)).thenReturn(false);
|
|
|
|
|
when(nioAccess.isRegularFile(path)).thenReturn(false);
|
|
|
|
|
FileChannel channel = mock(FileChannel.class);
|
|
|
|
|
AsynchronousFileChannel channel = mock(AsynchronousFileChannel.class);
|
|
|
|
|
when(nioAccess.open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)).thenReturn(channel);
|
|
|
|
|
inTest.open(OpenMode.WRITE);
|
|
|
|
|
|
|
|
|
|
@@ -175,7 +177,7 @@ public class SharedFileChannelTest {
|
|
|
|
|
public void testCloseWrapsIOExceptionFromForceInUncheckedIOExceptionAndStillClosesChannel() throws IOException {
|
|
|
|
|
when(nioAccess.isDirectory(path)).thenReturn(false);
|
|
|
|
|
when(nioAccess.isRegularFile(path)).thenReturn(false);
|
|
|
|
|
FileChannel channel = mock(FileChannel.class);
|
|
|
|
|
AsynchronousFileChannel channel = mock(AsynchronousFileChannel.class);
|
|
|
|
|
when(nioAccess.open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)).thenReturn(channel);
|
|
|
|
|
inTest.open(OpenMode.WRITE);
|
|
|
|
|
IOException exceptionFromForce = new IOException();
|
|
|
|
|
@@ -195,7 +197,7 @@ public class SharedFileChannelTest {
|
|
|
|
|
public void testCloseWrapsIOExceptionFromCloseInUncheckedIOException() throws IOException {
|
|
|
|
|
when(nioAccess.isDirectory(path)).thenReturn(false);
|
|
|
|
|
when(nioAccess.isRegularFile(path)).thenReturn(false);
|
|
|
|
|
FileChannel channel = mock(FileChannel.class);
|
|
|
|
|
AsynchronousFileChannel channel = mock(AsynchronousFileChannel.class);
|
|
|
|
|
when(nioAccess.open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)).thenReturn(channel);
|
|
|
|
|
inTest.open(OpenMode.WRITE);
|
|
|
|
|
IOException exceptionFromClose = new IOException();
|
|
|
|
|
@@ -211,7 +213,7 @@ public class SharedFileChannelTest {
|
|
|
|
|
public void testCloseDoesNotCloseChannelIfOpenedTwice() throws IOException {
|
|
|
|
|
when(nioAccess.isDirectory(path)).thenReturn(false);
|
|
|
|
|
when(nioAccess.isRegularFile(path)).thenReturn(false);
|
|
|
|
|
FileChannel channel = mock(FileChannel.class);
|
|
|
|
|
AsynchronousFileChannel channel = mock(AsynchronousFileChannel.class);
|
|
|
|
|
when(nioAccess.open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)).thenReturn(channel);
|
|
|
|
|
inTest.open(OpenMode.WRITE);
|
|
|
|
|
inThreadRethrowingException(() -> inTest.open(OpenMode.WRITE));
|
|
|
|
|
@@ -225,7 +227,7 @@ public class SharedFileChannelTest {
|
|
|
|
|
public void testLastCloseDoesCloseChannelIfOpenedTwice() throws IOException {
|
|
|
|
|
when(nioAccess.isDirectory(path)).thenReturn(false);
|
|
|
|
|
when(nioAccess.isRegularFile(path)).thenReturn(false);
|
|
|
|
|
FileChannel channel = mock(FileChannel.class);
|
|
|
|
|
AsynchronousFileChannel channel = mock(AsynchronousFileChannel.class);
|
|
|
|
|
when(nioAccess.open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)).thenReturn(channel);
|
|
|
|
|
inTest.open(OpenMode.WRITE);
|
|
|
|
|
inThreadRethrowingException(() -> {
|
|
|
|
|
@@ -245,25 +247,27 @@ public class SharedFileChannelTest {
|
|
|
|
|
@Rule
|
|
|
|
|
public Timeout timeoutRule = Timeout.seconds(1);
|
|
|
|
|
|
|
|
|
|
private FileChannel channel;
|
|
|
|
|
private AsynchronousFileChannel channel;
|
|
|
|
|
|
|
|
|
|
@Before
|
|
|
|
|
public void setUp() throws IOException {
|
|
|
|
|
when(nioAccess.isDirectory(path)).thenReturn(false);
|
|
|
|
|
when(nioAccess.isRegularFile(path)).thenReturn(true);
|
|
|
|
|
channel = mock(FileChannel.class);
|
|
|
|
|
channel = mock(AsynchronousFileChannel.class);
|
|
|
|
|
when(nioAccess.open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)).thenReturn(channel);
|
|
|
|
|
inTest.open(OpenMode.READ);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void testReadFullyWrapsExceptionFromReadInUncheckedIOException() throws IOException {
|
|
|
|
|
public void testReadFullyWrapsExceptionFromReadInUncheckedIOException() throws InterruptedException, ExecutionException {
|
|
|
|
|
ByteBuffer buffer = ByteBuffer.allocate(0);
|
|
|
|
|
IOException exceptionFromRead = new IOException();
|
|
|
|
|
when(channel.read(buffer, 0)).thenThrow(exceptionFromRead);
|
|
|
|
|
ExecutionException exceptionFromRead = new ExecutionException(new IOException());
|
|
|
|
|
Future<Integer> result = mock(Future.class);
|
|
|
|
|
when(channel.read(buffer, 0)).thenReturn(result);
|
|
|
|
|
when(result.get()).thenThrow(exceptionFromRead);
|
|
|
|
|
|
|
|
|
|
thrown.expect(UncheckedIOException.class);
|
|
|
|
|
thrown.expectCause(is(exceptionFromRead));
|
|
|
|
|
thrown.expectCause(is(instanceOf(IOException.class))); // TODO check correct cause of cause
|
|
|
|
|
|
|
|
|
|
inTest.readFully(0, buffer);
|
|
|
|
|
}
|
|
|
|
|
@@ -271,11 +275,11 @@ public class SharedFileChannelTest {
|
|
|
|
|
@Test
|
|
|
|
|
public void testReadFullyDelegatesToChannelRead() throws IOException {
|
|
|
|
|
ByteBuffer buffer = ByteBuffer.allocate(50);
|
|
|
|
|
when(channel.read(buffer, 0)).thenAnswer(new Answer<Integer>() {
|
|
|
|
|
when(channel.read(buffer, 0)).thenAnswer(new Answer<Future<Integer>>() {
|
|
|
|
|
@Override
|
|
|
|
|
public Integer answer(InvocationOnMock invocation) throws Throwable {
|
|
|
|
|
public Future<Integer> answer(InvocationOnMock invocation) throws Throwable {
|
|
|
|
|
buffer.position(50);
|
|
|
|
|
return 50;
|
|
|
|
|
return constantFuture(50);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
@@ -289,7 +293,7 @@ public class SharedFileChannelTest {
|
|
|
|
|
@Test
|
|
|
|
|
public void testReadFullyReturnsEofWhenFirstReadReturnsIt() throws IOException {
|
|
|
|
|
ByteBuffer buffer = ByteBuffer.allocate(50);
|
|
|
|
|
when(channel.read(buffer, 0)).thenReturn(EOF);
|
|
|
|
|
when(channel.read(buffer, 0)).thenReturn(constantFuture(EOF));
|
|
|
|
|
|
|
|
|
|
int result = inTest.readFully(0, buffer);
|
|
|
|
|
|
|
|
|
|
@@ -302,7 +306,7 @@ public class SharedFileChannelTest {
|
|
|
|
|
public void testReadStopsReadingIfEofIsReached() throws IOException {
|
|
|
|
|
ByteBuffer buffer = ByteBuffer.allocate(50);
|
|
|
|
|
when(channel.read(buffer, 0)).thenAnswer(simulateRead(20, buffer));
|
|
|
|
|
when(channel.read(buffer, 20)).thenReturn(EOF);
|
|
|
|
|
when(channel.read(buffer, 20)).thenReturn(constantFuture(EOF));
|
|
|
|
|
|
|
|
|
|
int result = inTest.readFully(0, buffer);
|
|
|
|
|
|
|
|
|
|
@@ -328,12 +332,12 @@ public class SharedFileChannelTest {
|
|
|
|
|
verifyNoMoreInteractions(channel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Answer<Integer> simulateRead(int amount, ByteBuffer target) {
|
|
|
|
|
return new Answer<Integer>() {
|
|
|
|
|
private Answer<Future<Integer>> simulateRead(int amount, ByteBuffer target) {
|
|
|
|
|
return new Answer<Future<Integer>>() {
|
|
|
|
|
@Override
|
|
|
|
|
public Integer answer(InvocationOnMock invocation) throws Throwable {
|
|
|
|
|
public Future<Integer> answer(InvocationOnMock invocation) throws Throwable {
|
|
|
|
|
target.position(target.position() + amount);
|
|
|
|
|
return amount;
|
|
|
|
|
return constantFuture(amount);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
@@ -342,13 +346,13 @@ public class SharedFileChannelTest {
|
|
|
|
|
|
|
|
|
|
public class Truncate {
|
|
|
|
|
|
|
|
|
|
private FileChannel channel;
|
|
|
|
|
private AsynchronousFileChannel channel;
|
|
|
|
|
|
|
|
|
|
@Before
|
|
|
|
|
public void setUp() throws IOException {
|
|
|
|
|
when(nioAccess.isDirectory(path)).thenReturn(false);
|
|
|
|
|
when(nioAccess.isRegularFile(path)).thenReturn(true);
|
|
|
|
|
channel = mock(FileChannel.class);
|
|
|
|
|
channel = mock(AsynchronousFileChannel.class);
|
|
|
|
|
when(nioAccess.open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)).thenReturn(channel);
|
|
|
|
|
inTest.open(OpenMode.WRITE);
|
|
|
|
|
}
|
|
|
|
|
@@ -378,13 +382,13 @@ public class SharedFileChannelTest {
|
|
|
|
|
|
|
|
|
|
public class Size {
|
|
|
|
|
|
|
|
|
|
private FileChannel channel;
|
|
|
|
|
private AsynchronousFileChannel channel;
|
|
|
|
|
|
|
|
|
|
@Before
|
|
|
|
|
public void setUp() throws IOException {
|
|
|
|
|
when(nioAccess.isDirectory(path)).thenReturn(false);
|
|
|
|
|
when(nioAccess.isRegularFile(path)).thenReturn(true);
|
|
|
|
|
channel = mock(FileChannel.class);
|
|
|
|
|
channel = mock(AsynchronousFileChannel.class);
|
|
|
|
|
when(nioAccess.open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)).thenReturn(channel);
|
|
|
|
|
inTest.open(OpenMode.WRITE);
|
|
|
|
|
}
|
|
|
|
|
@@ -412,148 +416,151 @@ public class SharedFileChannelTest {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class TransferTo {
|
|
|
|
|
|
|
|
|
|
private FileChannel channel;
|
|
|
|
|
|
|
|
|
|
private Path targetPath;
|
|
|
|
|
private SharedFileChannel targetInTest;
|
|
|
|
|
private FileChannel targetChannel;
|
|
|
|
|
|
|
|
|
|
@Before
|
|
|
|
|
public void setUp() throws IOException {
|
|
|
|
|
targetPath = mock(Path.class);
|
|
|
|
|
targetInTest = new SharedFileChannel(targetPath, nioAccess);
|
|
|
|
|
|
|
|
|
|
when(nioAccess.isDirectory(path)).thenReturn(false);
|
|
|
|
|
when(nioAccess.isRegularFile(path)).thenReturn(true);
|
|
|
|
|
channel = mock(FileChannel.class);
|
|
|
|
|
when(nioAccess.open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)).thenReturn(channel);
|
|
|
|
|
inTest.open(OpenMode.WRITE);
|
|
|
|
|
|
|
|
|
|
when(nioAccess.isDirectory(targetPath)).thenReturn(false);
|
|
|
|
|
when(nioAccess.isRegularFile(targetPath)).thenReturn(true);
|
|
|
|
|
targetChannel = mock(FileChannel.class);
|
|
|
|
|
when(nioAccess.open(targetPath, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)).thenReturn(targetChannel);
|
|
|
|
|
targetInTest.open(OpenMode.WRITE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void testTransferToThrowsIllegalArugmentExceptionIfCountIsNegative() {
|
|
|
|
|
thrown.expect(IllegalArgumentException.class);
|
|
|
|
|
thrown.expectMessage("Count must not be negative");
|
|
|
|
|
|
|
|
|
|
inTest.transferTo(0, -1, targetInTest, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void testTransferToSetsPositionOfTargetChannelAndThenDelegatesToChannelsTransferTo() throws IOException {
|
|
|
|
|
long targetPosition = 43L;
|
|
|
|
|
long startPosition = 22L;
|
|
|
|
|
long count = 39L;
|
|
|
|
|
when(channel.transferTo(startPosition, count, targetChannel)).thenReturn(count);
|
|
|
|
|
when(channel.size()).thenReturn(startPosition + count);
|
|
|
|
|
|
|
|
|
|
long result = inTest.transferTo(startPosition, count, targetInTest, targetPosition);
|
|
|
|
|
|
|
|
|
|
assertThat(result, is(count));
|
|
|
|
|
InOrder inOrder = inOrder(channel, targetChannel);
|
|
|
|
|
inOrder.verify(targetChannel).position(targetPosition);
|
|
|
|
|
inOrder.verify(channel).transferTo(startPosition, count, targetChannel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void testTransferToInvokesTransferUntilAllBytesHaveBeenTransferred() throws IOException {
|
|
|
|
|
long targetPosition = 43L;
|
|
|
|
|
long startPosition = 22L;
|
|
|
|
|
long count = 39L;
|
|
|
|
|
long firstTransferCount = 10L;
|
|
|
|
|
long secondTransferCount = 7L;
|
|
|
|
|
long thridTransferCount = count - firstTransferCount - secondTransferCount;
|
|
|
|
|
when(channel.transferTo(startPosition, count, targetChannel)).thenReturn(firstTransferCount);
|
|
|
|
|
when(channel.transferTo(startPosition + firstTransferCount, count - firstTransferCount, targetChannel)).thenReturn(secondTransferCount);
|
|
|
|
|
when(channel.transferTo(startPosition + firstTransferCount + secondTransferCount, thridTransferCount, targetChannel)).thenReturn(thridTransferCount);
|
|
|
|
|
when(channel.size()).thenReturn(startPosition + count);
|
|
|
|
|
|
|
|
|
|
long result = inTest.transferTo(startPosition, count, targetInTest, targetPosition);
|
|
|
|
|
|
|
|
|
|
assertThat(result, is(count));
|
|
|
|
|
InOrder inOrder = inOrder(channel, targetChannel);
|
|
|
|
|
inOrder.verify(targetChannel).position(targetPosition);
|
|
|
|
|
inOrder.verify(channel).transferTo(startPosition, count, targetChannel);
|
|
|
|
|
inOrder.verify(channel).transferTo(startPosition + firstTransferCount, count - firstTransferCount, targetChannel);
|
|
|
|
|
inOrder.verify(channel).transferTo(startPosition + firstTransferCount + secondTransferCount, thridTransferCount, targetChannel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void testTransferToStopsTransferAtEndOfSourceFile() throws IOException {
|
|
|
|
|
long targetPosition = 43L;
|
|
|
|
|
long startPosition = 22L;
|
|
|
|
|
long count = 39L;
|
|
|
|
|
long countAvailable = 30L;
|
|
|
|
|
when(channel.transferTo(startPosition, countAvailable, targetChannel)).thenReturn(countAvailable);
|
|
|
|
|
when(channel.size()).thenReturn(startPosition + countAvailable);
|
|
|
|
|
|
|
|
|
|
long result = inTest.transferTo(startPosition, count, targetInTest, targetPosition);
|
|
|
|
|
|
|
|
|
|
assertThat(result, is(countAvailable));
|
|
|
|
|
InOrder inOrder = inOrder(channel, targetChannel);
|
|
|
|
|
inOrder.verify(targetChannel).position(targetPosition);
|
|
|
|
|
inOrder.verify(channel).transferTo(startPosition, countAvailable, targetChannel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void testTransferToWrapsIOExceptionFromPositionInUncheckedIOException() throws IOException {
|
|
|
|
|
when(channel.size()).thenReturn(Long.MAX_VALUE);
|
|
|
|
|
IOException exceptionFromPosition = new IOException();
|
|
|
|
|
when(targetChannel.position(anyLong())).thenThrow(exceptionFromPosition);
|
|
|
|
|
|
|
|
|
|
thrown.expect(UncheckedIOException.class);
|
|
|
|
|
thrown.expectCause(is(exceptionFromPosition));
|
|
|
|
|
|
|
|
|
|
inTest.transferTo(0L, 10L, targetInTest, 0L);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void testTransferToWrapsIOExceptionFromTransferToInUncheckedIOException() throws IOException {
|
|
|
|
|
when(channel.size()).thenReturn(Long.MAX_VALUE);
|
|
|
|
|
IOException exceptionFromTransferTo = new IOException();
|
|
|
|
|
when(channel.transferTo(anyLong(), anyLong(), any())).thenThrow(exceptionFromTransferTo);
|
|
|
|
|
|
|
|
|
|
thrown.expect(UncheckedIOException.class);
|
|
|
|
|
thrown.expectCause(is(exceptionFromTransferTo));
|
|
|
|
|
|
|
|
|
|
inTest.transferTo(0L, 10L, targetInTest, 0L);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
// TODO fix / implement tests
|
|
|
|
|
// public class TransferTo {
|
|
|
|
|
//
|
|
|
|
|
// private AsynchronousFileChannel channel;
|
|
|
|
|
//
|
|
|
|
|
// private Path targetPath;
|
|
|
|
|
// private SharedFileChannel targetInTest;
|
|
|
|
|
// private AsynchronousFileChannel targetChannel;
|
|
|
|
|
//
|
|
|
|
|
// @Before
|
|
|
|
|
// public void setUp() throws IOException {
|
|
|
|
|
// targetPath = mock(Path.class);
|
|
|
|
|
// targetInTest = new SharedFileChannel(targetPath, nioAccess);
|
|
|
|
|
//
|
|
|
|
|
// when(nioAccess.isDirectory(path)).thenReturn(false);
|
|
|
|
|
// when(nioAccess.isRegularFile(path)).thenReturn(true);
|
|
|
|
|
// channel = mock(AsynchronousFileChannel.class);
|
|
|
|
|
// when(nioAccess.open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)).thenReturn(channel);
|
|
|
|
|
// inTest.open(OpenMode.WRITE);
|
|
|
|
|
//
|
|
|
|
|
// when(nioAccess.isDirectory(targetPath)).thenReturn(false);
|
|
|
|
|
// when(nioAccess.isRegularFile(targetPath)).thenReturn(true);
|
|
|
|
|
// targetChannel = mock(AsynchronousFileChannel.class);
|
|
|
|
|
// when(nioAccess.open(targetPath, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)).thenReturn(targetChannel);
|
|
|
|
|
// targetInTest.open(OpenMode.WRITE);
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// @Test
|
|
|
|
|
// public void testTransferToThrowsIllegalArugmentExceptionIfCountIsNegative() {
|
|
|
|
|
// thrown.expect(IllegalArgumentException.class);
|
|
|
|
|
// thrown.expectMessage("Count must not be negative");
|
|
|
|
|
//
|
|
|
|
|
// inTest.transferTo(0, -1, targetInTest, 0);
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// @Test
|
|
|
|
|
// public void testTransferToSetsPositionOfTargetChannelAndThenDelegatesToChannelsTransferTo() throws IOException {
|
|
|
|
|
// long targetPosition = 43L;
|
|
|
|
|
// long startPosition = 22L;
|
|
|
|
|
// long count = 39L;
|
|
|
|
|
// when(channel.transferTo(startPosition, count, targetChannel)).thenReturn(count);
|
|
|
|
|
// when(channel.size()).thenReturn(startPosition + count);
|
|
|
|
|
//
|
|
|
|
|
// long result = inTest.transferTo(startPosition, count, targetInTest, targetPosition);
|
|
|
|
|
//
|
|
|
|
|
// assertThat(result, is(count));
|
|
|
|
|
// InOrder inOrder = inOrder(channel, targetChannel);
|
|
|
|
|
// inOrder.verify(targetChannel).position(targetPosition);
|
|
|
|
|
// inOrder.verify(channel).transferTo(startPosition, count, targetChannel);
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// @Test
|
|
|
|
|
// public void testTransferToInvokesTransferUntilAllBytesHaveBeenTransferred() throws IOException {
|
|
|
|
|
// long targetPosition = 43L;
|
|
|
|
|
// long startPosition = 22L;
|
|
|
|
|
// long count = 39L;
|
|
|
|
|
// long firstTransferCount = 10L;
|
|
|
|
|
// long secondTransferCount = 7L;
|
|
|
|
|
// long thridTransferCount = count - firstTransferCount - secondTransferCount;
|
|
|
|
|
// when(channel.transferTo(startPosition, count, targetChannel)).thenReturn(firstTransferCount);
|
|
|
|
|
// when(channel.transferTo(startPosition + firstTransferCount, count - firstTransferCount, targetChannel)).thenReturn(secondTransferCount);
|
|
|
|
|
// when(channel.transferTo(startPosition + firstTransferCount + secondTransferCount, thridTransferCount, targetChannel)).thenReturn(thridTransferCount);
|
|
|
|
|
// when(channel.size()).thenReturn(startPosition + count);
|
|
|
|
|
//
|
|
|
|
|
// long result = inTest.transferTo(startPosition, count, targetInTest, targetPosition);
|
|
|
|
|
//
|
|
|
|
|
// assertThat(result, is(count));
|
|
|
|
|
// InOrder inOrder = inOrder(channel, targetChannel);
|
|
|
|
|
// inOrder.verify(targetChannel).position(targetPosition);
|
|
|
|
|
// inOrder.verify(channel).transferTo(startPosition, count, targetChannel);
|
|
|
|
|
// inOrder.verify(channel).transferTo(startPosition + firstTransferCount, count - firstTransferCount, targetChannel);
|
|
|
|
|
// inOrder.verify(channel).transferTo(startPosition + firstTransferCount + secondTransferCount, thridTransferCount, targetChannel);
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// @Test
|
|
|
|
|
// public void testTransferToStopsTransferAtEndOfSourceFile() throws IOException {
|
|
|
|
|
// long targetPosition = 43L;
|
|
|
|
|
// long startPosition = 22L;
|
|
|
|
|
// long count = 39L;
|
|
|
|
|
// long countAvailable = 30L;
|
|
|
|
|
// when(channel.transferTo(startPosition, countAvailable, targetChannel)).thenReturn(countAvailable);
|
|
|
|
|
// when(channel.size()).thenReturn(startPosition + countAvailable);
|
|
|
|
|
//
|
|
|
|
|
// long result = inTest.transferTo(startPosition, count, targetInTest, targetPosition);
|
|
|
|
|
//
|
|
|
|
|
// assertThat(result, is(countAvailable));
|
|
|
|
|
// InOrder inOrder = inOrder(channel, targetChannel);
|
|
|
|
|
// inOrder.verify(targetChannel).position(targetPosition);
|
|
|
|
|
// inOrder.verify(channel).transferTo(startPosition, countAvailable, targetChannel);
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// @Test
|
|
|
|
|
// public void testTransferToWrapsIOExceptionFromPositionInUncheckedIOException() throws IOException {
|
|
|
|
|
// when(channel.size()).thenReturn(Long.MAX_VALUE);
|
|
|
|
|
// IOException exceptionFromPosition = new IOException();
|
|
|
|
|
// when(targetChannel.position(anyLong())).thenThrow(exceptionFromPosition);
|
|
|
|
|
//
|
|
|
|
|
// thrown.expect(UncheckedIOException.class);
|
|
|
|
|
// thrown.expectCause(is(exceptionFromPosition));
|
|
|
|
|
//
|
|
|
|
|
// inTest.transferTo(0L, 10L, targetInTest, 0L);
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// @Test
|
|
|
|
|
// public void testTransferToWrapsIOExceptionFromTransferToInUncheckedIOException() throws IOException {
|
|
|
|
|
// when(channel.size()).thenReturn(Long.MAX_VALUE);
|
|
|
|
|
// IOException exceptionFromTransferTo = new IOException();
|
|
|
|
|
// when(channel.transferTo(anyLong(), anyLong(), any())).thenThrow(exceptionFromTransferTo);
|
|
|
|
|
//
|
|
|
|
|
// thrown.expect(UncheckedIOException.class);
|
|
|
|
|
// thrown.expectCause(is(exceptionFromTransferTo));
|
|
|
|
|
//
|
|
|
|
|
// inTest.transferTo(0L, 10L, targetInTest, 0L);
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
public class WriteFully {
|
|
|
|
|
|
|
|
|
|
@Rule
|
|
|
|
|
public Timeout timeoutRule = Timeout.seconds(1);
|
|
|
|
|
|
|
|
|
|
private FileChannel channel;
|
|
|
|
|
private AsynchronousFileChannel channel;
|
|
|
|
|
|
|
|
|
|
@Before
|
|
|
|
|
public void setUp() throws IOException {
|
|
|
|
|
when(nioAccess.isDirectory(path)).thenReturn(false);
|
|
|
|
|
when(nioAccess.isRegularFile(path)).thenReturn(true);
|
|
|
|
|
channel = mock(FileChannel.class);
|
|
|
|
|
channel = mock(AsynchronousFileChannel.class);
|
|
|
|
|
when(nioAccess.open(path, StandardOpenOption.CREATE, StandardOpenOption.READ, StandardOpenOption.WRITE)).thenReturn(channel);
|
|
|
|
|
inTest.open(OpenMode.WRITE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void testWriteFullyWrapsIOExceptionFromWriteIntoUncheckedIOException() throws IOException {
|
|
|
|
|
public void testWriteFullyWrapsIOExceptionFromWriteIntoUncheckedIOException() throws InterruptedException, ExecutionException {
|
|
|
|
|
int count = 1;
|
|
|
|
|
int position = 0;
|
|
|
|
|
ByteBuffer buffer = ByteBuffer.allocate(count);
|
|
|
|
|
IOException exceptionFromWrite = new IOException();
|
|
|
|
|
when(channel.write(buffer, position)).thenThrow(exceptionFromWrite);
|
|
|
|
|
ExecutionException exceptionFromWrite = new ExecutionException(new IOException());
|
|
|
|
|
Future<Integer> result = mock(Future.class);
|
|
|
|
|
when(channel.write(buffer, position)).thenReturn(result);
|
|
|
|
|
when(result.get()).thenThrow(exceptionFromWrite);
|
|
|
|
|
|
|
|
|
|
thrown.expect(UncheckedIOException.class);
|
|
|
|
|
thrown.expectCause(is(exceptionFromWrite));
|
|
|
|
|
thrown.expectCause(is(instanceOf(IOException.class))); // TODO check correct cause of cause
|
|
|
|
|
|
|
|
|
|
inTest.writeFully(position, buffer);
|
|
|
|
|
}
|
|
|
|
|
@@ -604,12 +611,12 @@ public class SharedFileChannelTest {
|
|
|
|
|
verify(channel).write(buffer, position);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Answer<Integer> simulateWrite(int amount, ByteBuffer target) {
|
|
|
|
|
return new Answer<Integer>() {
|
|
|
|
|
private Answer<Future<Integer>> simulateWrite(int amount, ByteBuffer target) {
|
|
|
|
|
return new Answer<Future<Integer>>() {
|
|
|
|
|
@Override
|
|
|
|
|
public Integer answer(InvocationOnMock invocation) throws Throwable {
|
|
|
|
|
public Future<Integer> answer(InvocationOnMock invocation) throws Throwable {
|
|
|
|
|
target.position(target.position() + amount);
|
|
|
|
|
return amount;
|
|
|
|
|
return constantFuture(amount);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|