package rocks.inspectit.shared.cs.storage.nio; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousFileChannel; import java.nio.channels.CompletionHandler; import java.util.Random; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import rocks.inspectit.shared.cs.storage.nio.read.ReadingCompletionHandler; import rocks.inspectit.shared.cs.storage.nio.write.WritingCompletionHandler; @SuppressWarnings("PMD") public class CompletionHandlersTest { private WritingCompletionHandler writingCompletionHandler = new WritingCompletionHandler(); private ReadingCompletionHandler readingCompletionHandler = new ReadingCompletionHandler(); @Mock private WriteReadAttachment attachment; @Mock private ByteBuffer byteBuffer; @Mock private WriteReadCompletionRunnable.RunnableFuture writeReadRunnableFuture; @Mock private WriteReadCompletionRunnable writeReadRunnable; @Mock private AsynchronousFileChannel channel; @BeforeMethod public void initMock() { MockitoAnnotations.initMocks(this); when(writeReadRunnableFuture.getWriteReadCompletionRunnable()).thenReturn(writeReadRunnable); when(attachment.getCompletionRunnableFuture()).thenReturn(writeReadRunnableFuture); when(attachment.getFileChannel()).thenReturn(channel); when(attachment.getByteBuffer()).thenReturn(byteBuffer); } @Test(dataProvider = "Handlers") public void writeReadFailedNotCompleted(CompletionHandler<Integer, WriteReadAttachment> handler) { Exception exception = new Exception(); when(writeReadRunnable.isFinished()).thenReturn(false); handler.failed(exception, attachment); verify(attachment).getCompletionRunnableFuture(); verify(writeReadRunnable).isFinished(); verify(writeReadRunnable).markFailed(); verify(writeReadRunnableFuture, times(2)).getWriteReadCompletionRunnable(); verifyNoMoreInteractions(writeReadRunnable, writeReadRunnableFuture); verifyZeroInteractions(channel, byteBuffer); } @Test(dataProvider = "Handlers") public void writeReadFailedCompleted(CompletionHandler<Integer, WriteReadAttachment> handler) { Exception exception = new Exception(); when(writeReadRunnable.isFinished()).thenReturn(true); handler.failed(exception, attachment); verify(attachment).getCompletionRunnableFuture(); verify(writeReadRunnable).isFinished(); verify(writeReadRunnable).markFailed(); verify(writeReadRunnableFuture).run(); verify(writeReadRunnableFuture, times(2)).getWriteReadCompletionRunnable(); verifyNoMoreInteractions(writeReadRunnable, writeReadRunnableFuture); verifyZeroInteractions(channel, byteBuffer); } @Test(dataProvider = "Handlers") public void writeReadFinishedNotCompleted(CompletionHandler<Integer, WriteReadAttachment> handler) { int size = 50; Integer bytesRead = Integer.valueOf(size); when(attachment.getPosition()).thenReturn(0L); when(attachment.getSize()).thenReturn((long) size); when(writeReadRunnable.isFinished()).thenReturn(false); handler.completed(bytesRead, attachment); verify(attachment).getCompletionRunnableFuture(); verify(writeReadRunnable).isFinished(); verify(writeReadRunnable).markSuccess(); verify(writeReadRunnableFuture, times(2)).getWriteReadCompletionRunnable(); verifyNoMoreInteractions(writeReadRunnable, writeReadRunnableFuture); verifyZeroInteractions(channel, byteBuffer); } @Test(dataProvider = "Handlers") public void writeReadFinishedCompleted(CompletionHandler<Integer, WriteReadAttachment> handler) { int size = 50; Integer bytesRead = Integer.valueOf(size); when(attachment.getPosition()).thenReturn(0L); when(attachment.getSize()).thenReturn((long) size); when(writeReadRunnable.isFinished()).thenReturn(true); handler.completed(bytesRead, attachment); verify(attachment).getCompletionRunnableFuture(); verify(writeReadRunnable).isFinished(); verify(writeReadRunnable).markSuccess(); verify(writeReadRunnableFuture).run(); verify(writeReadRunnableFuture, times(2)).getWriteReadCompletionRunnable(); verifyNoMoreInteractions(writeReadRunnable, writeReadRunnableFuture); verifyZeroInteractions(channel, byteBuffer); } @DataProvider(name = "Handlers") public Object[][] handlerProviders() { return new Object[][] { { writingCompletionHandler }, { readingCompletionHandler } }; } @Test(dataProvider = "Write-Read-Data-Provider") public void hasMoreToWrite(int written, long wantedPosition, long wantedSize) { Integer bytesRead = Integer.valueOf(written); when(attachment.getPosition()).thenReturn(wantedPosition); when(attachment.getSize()).thenReturn(wantedSize); when(writeReadRunnable.isFinished()).thenReturn(false); writingCompletionHandler.completed(bytesRead, attachment); verify(attachment).setPosition(wantedPosition + written); verify(attachment).setSize(wantedSize - written); verify(channel, times(1)).write(byteBuffer, wantedPosition + written, attachment, writingCompletionHandler); verifyZeroInteractions(writeReadRunnableFuture, byteBuffer); } @Test(dataProvider = "Write-Read-Data-Provider") public void hasMoreToRead(int read, long wantedPosition, long wantedSize) { Integer bytesRead = Integer.valueOf(read); when(attachment.getPosition()).thenReturn(wantedPosition); when(attachment.getSize()).thenReturn(wantedSize); when(writeReadRunnable.isFinished()).thenReturn(false); readingCompletionHandler.completed(bytesRead, attachment); verify(attachment).setPosition(wantedPosition + read); verify(attachment).setSize(wantedSize - read); verify(channel, times(1)).read(byteBuffer, wantedPosition + read, attachment, readingCompletionHandler); verifyZeroInteractions(writeReadRunnableFuture, byteBuffer); } @DataProvider(name = "Write-Read-Data-Provider") public Object[][] writeDataProvider() { Random random = new Random(); int size = random.nextInt(25); Object[][] data = new Object[size][3]; for (int i = 0; i < size; i++) { int written = random.nextInt(10000); long wantedSize = random.nextInt(100000) + written; long wantedPosition = random.nextInt(100000); data[i][0] = written; data[i][1] = wantedPosition; data[i][2] = wantedSize; } return data; } }