package rocks.inspectit.shared.all.storage.nio.stream; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.Random; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.slf4j.Logger; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import rocks.inspectit.shared.all.storage.nio.ByteBufferProvider; import rocks.inspectit.shared.all.testbase.TestBase; @SuppressWarnings("PMD") public class SocketExtendedByteBufferInputStreamTest extends TestBase { private static final int NUMBER_OF_BUFFERS = 2; /** * Class under test. */ SocketExtendedByteBufferInputStream inputStream; @Mock ByteBufferProvider byteBufferProvider; @Mock SocketChannel socketChannel; @Mock Logger log; /** * Executor service needed for the handler. Can not be mocked. */ ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1); /** * Init. */ @BeforeMethod public void init() { inputStream = new SocketExtendedByteBufferInputStream(NUMBER_OF_BUFFERS); inputStream.setByteBufferProvider(byteBufferProvider); inputStream.setExecutorService(executorService); inputStream.setSocketChannel(socketChannel); inputStream.setLog(log); } public static class Read extends SocketExtendedByteBufferInputStreamTest { /** * Tests reading of random size. * * @throws IOException */ @Test(invocationCount = 50) public void read() throws IOException { Random random = new Random(); final int readSize = random.nextInt(8096); final int bufferSize = 1024; final byte[] array = new byte[readSize]; random.nextBytes(array); when(byteBufferProvider.acquireByteBuffer()).thenAnswer(new Answer<ByteBuffer>() { @Override public ByteBuffer answer(InvocationOnMock invocation) throws Throwable { return ByteBuffer.allocateDirect(bufferSize); } }); when(socketChannel.read(Matchers.<ByteBuffer> any())).thenAnswer(new Answer<Integer>() { int readPosition = 0; @Override public Integer answer(InvocationOnMock invocation) throws Throwable { Object[] args = invocation.getArguments(); ByteBuffer byteBuffer = (ByteBuffer) args[0]; int remaining = byteBuffer.remaining(); int toRead = remaining > (array.length - readPosition) ? array.length - readPosition : remaining; byteBuffer.put(array, readPosition, toRead); int newRemaning = byteBuffer.remaining(); readPosition += remaining - newRemaning; return remaining - newRemaning; } }); inputStream.prepare(); inputStream.reset(readSize); byte[] bytes = new byte[readSize]; int read = inputStream.read(bytes, 0, readSize); if (readSize > 0) { assertThat(read, is(readSize)); } else { assertThat(read, is(-1)); } assertThat(bytes, is(equalTo(array))); inputStream.close(); verify(byteBufferProvider, times(NUMBER_OF_BUFFERS)).releaseByteBuffer(Matchers.<ByteBuffer> anyObject()); } @Test(expectedExceptions = IOException.class) public void endOfStream() throws IOException { Random random = new Random(); final int readSize = 1 + random.nextInt(8096); final int bufferSize = 1024; final byte[] array = new byte[readSize]; random.nextBytes(array); when(byteBufferProvider.acquireByteBuffer()).thenAnswer(new Answer<ByteBuffer>() { @Override public ByteBuffer answer(InvocationOnMock invocation) throws Throwable { return ByteBuffer.allocateDirect(bufferSize); } }); when(socketChannel.read(Matchers.<ByteBuffer> any())).thenAnswer(new Answer<Integer>() { @Override public Integer answer(InvocationOnMock invocation) throws Throwable { return -1; } }); inputStream.prepare(); inputStream.reset(readSize); byte[] bytes = new byte[readSize]; inputStream.read(bytes, 0, readSize); } @Test(expectedExceptions = IOException.class) public void ioExceptionOnRead() throws IOException { Random random = new Random(); final int readSize = 1 + random.nextInt(8096); final int bufferSize = 1024; final byte[] array = new byte[readSize]; random.nextBytes(array); when(byteBufferProvider.acquireByteBuffer()).thenAnswer(new Answer<ByteBuffer>() { @Override public ByteBuffer answer(InvocationOnMock invocation) throws Throwable { return ByteBuffer.allocateDirect(bufferSize); } }); doThrow(IOException.class).when(socketChannel).read(Matchers.<ByteBuffer> any()); inputStream.prepare(); inputStream.reset(readSize); byte[] bytes = new byte[readSize]; inputStream.read(bytes, 0, readSize); } } }