Search in sources :

Example 1 with WriteHandle

use of com.linkedin.r2.message.stream.entitystream.WriteHandle in project rest.li by linkedin.

the class TestEntityStream method testNoStackOverflow.

@Test
public void testNoStackOverflow() throws Exception {
    Writer dumbWriter = new Writer() {

        WriteHandle _wh;

        long _count = 0;

        final int _total = 1024 * 1024 * 1024;

        @Override
        public void onInit(WriteHandle wh) {
            _wh = wh;
        }

        @Override
        public void onWritePossible() {
            while (_wh.remaining() > 0 && _count < _total) {
                byte[] bytes = new byte[(int) Math.min(4096, _total - _count)];
                _wh.write(ByteString.copy(bytes));
                _count += bytes.length;
            }
            if (_count >= _total) {
                _wh.done();
            }
        }

        @Override
        public void onAbort(Throwable ex) {
        // do nothing
        }
    };
    Reader dumbReader = new Reader() {

        ReadHandle _rh;

        @Override
        public void onInit(ReadHandle rh) {
            _rh = rh;
            _rh.request(1);
        }

        @Override
        public void onDataAvailable(ByteString data) {
            _rh.request(1);
        }

        @Override
        public void onDone() {
        }

        @Override
        public void onError(Throwable e) {
        }
    };
    EntityStreams.newEntityStream(dumbWriter).setReader(dumbReader);
}
Also used : ReadHandle(com.linkedin.r2.message.stream.entitystream.ReadHandle) WriteHandle(com.linkedin.r2.message.stream.entitystream.WriteHandle) ByteString(com.linkedin.data.ByteString) Reader(com.linkedin.r2.message.stream.entitystream.Reader) Writer(com.linkedin.r2.message.stream.entitystream.Writer) Test(org.testng.annotations.Test)

Example 2 with WriteHandle

use of com.linkedin.r2.message.stream.entitystream.WriteHandle in project rest.li by linkedin.

the class TestReplaceableFilter method testStreamingPassThrough.

@Test
public void testStreamingPassThrough() {
    ReplaceableFilter filter = getFilter();
    CountRequestChunksFilter countRequestChunksFilter = new CountRequestChunksFilter();
    CountResponseChunksFilter countResponseChunksFilter = new CountResponseChunksFilter();
    FilterChain filterChain = FilterChains.empty().addLast(countResponseChunksFilter).addLast(filter).addLast(countRequestChunksFilter);
    int requestChunks = 100;
    int responseChunks = 200;
    StreamRequest streamRequest = new StreamRequestBuilder(URI.create("/test")).build(EntityStreams.newEntityStream(new Writer() {

        private WriteHandle _wh;

        int _count = 0;

        @Override
        public void onInit(WriteHandle wh) {
            _wh = wh;
        }

        @Override
        public void onWritePossible() {
            while (_wh.remaining() > 0) {
                if (_count < requestChunks) {
                    _wh.write(ByteString.copy(new byte[10]));
                    _count++;
                } else {
                    _wh.done();
                }
            }
        }

        @Override
        public void onAbort(Throwable e) {
        }
    }));
    StreamResponse streamResponse = new StreamResponseBuilder().build(EntityStreams.newEntityStream(new Writer() {

        private WriteHandle _wh;

        int _count = 0;

        @Override
        public void onInit(WriteHandle wh) {
            _wh = wh;
        }

        @Override
        public void onWritePossible() {
            while (_wh.remaining() > 0) {
                if (_count < responseChunks) {
                    _wh.write(ByteString.copy(new byte[10]));
                    _count++;
                } else {
                    _wh.done();
                }
            }
        }

        @Override
        public void onAbort(Throwable e) {
        }
    }));
    FilterUtil.fireStreamRequest(filterChain, streamRequest);
    FilterUtil.fireStreamResponse(filterChain, streamResponse, new RequestContext(), new HashMap<>());
    Assert.assertEquals(countRequestChunksFilter.getRequestChunks(), requestChunks);
    Assert.assertEquals(countResponseChunksFilter.getResponseChunks(), responseChunks);
}
Also used : StreamResponseBuilder(com.linkedin.r2.message.stream.StreamResponseBuilder) WriteHandle(com.linkedin.r2.message.stream.entitystream.WriteHandle) ReplaceableFilter(com.linkedin.r2.caprep.ReplaceableFilter) FilterChain(com.linkedin.r2.filter.FilterChain) StreamResponse(com.linkedin.r2.message.stream.StreamResponse) StreamRequestBuilder(com.linkedin.r2.message.stream.StreamRequestBuilder) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) RequestContext(com.linkedin.r2.message.RequestContext) Writer(com.linkedin.r2.message.stream.entitystream.Writer) BaseFilterTest(com.linkedin.r2.testutils.filter.BaseFilterTest) Test(org.testng.annotations.Test)

Example 3 with WriteHandle

use of com.linkedin.r2.message.stream.entitystream.WriteHandle in project rest.li by linkedin.

the class TestMIMEInputStream method testSingleOnWritePossibleDataSources.

@Test(dataProvider = "singleOnWritePossibleDataSources")
public void testSingleOnWritePossibleDataSources(final byte[] inputData, final StrictByteArrayInputStream inputStream, final int writesRemainingPerOnWritePossibles, final int expectedTotalWrites) {
    // Setup:
    final WriteHandle writeHandle = Mockito.mock(WriteHandle.class);
    final MultiPartMIMEInputStream multiPartMIMEInputStream = new MultiPartMIMEInputStream.Builder(inputStream, _scheduledExecutorService, Collections.<String, String>emptyMap()).withWriteChunkSize(TEST_CHUNK_SIZE).build();
    // Simulate a write handle that offers decreasing writeHandle.remaining()
    final Integer[] remainingWriteHandleCount = simulateDecreasingWriteHandleCount(writesRemainingPerOnWritePossibles);
    when(writeHandle.remaining()).thenReturn(writesRemainingPerOnWritePossibles, remainingWriteHandleCount);
    final ByteArrayOutputStream byteArrayOutputStream = setupMockWriteHandleToOutputStream(writeHandle);
    // Setup for done()
    final CountDownLatch doneLatch = new CountDownLatch(1);
    doAnswer(new Answer<Object>() {

        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            doneLatch.countDown();
            return null;
        }
    }).when(writeHandle).done();
    // /////////////////////////////////
    // Start things off
    // Init the data source
    multiPartMIMEInputStream.onInit(writeHandle);
    multiPartMIMEInputStream.onWritePossible();
    // Wait to finish
    try {
        boolean successful = doneLatch.await(_testTimeout, TimeUnit.MILLISECONDS);
        if (!successful) {
            Assert.fail("Timeout when waiting for input stream to completely transfer");
        }
    } catch (Exception exception) {
        Assert.fail("Unexpected exception when waiting for input stream to completely transfer");
    }
    // /////////////////////////////////
    // Assert
    Assert.assertEquals(byteArrayOutputStream.toByteArray(), inputData, "All data from the input stream should have successfully been transferred");
    Assert.assertEquals(inputStream.isClosed(), true);
    // Mock verifies:
    verify(writeHandle, times(expectedTotalWrites)).write(isA(ByteString.class));
    // One extra remaining() call for knowing the stream has ended.
    verify(writeHandle, times(expectedTotalWrites + 1)).remaining();
    verify(writeHandle, never()).error(isA(Throwable.class));
    verify(writeHandle, times(1)).done();
    verifyNoMoreInteractions(writeHandle);
}
Also used : WriteHandle(com.linkedin.r2.message.stream.entitystream.WriteHandle) ByteString(com.linkedin.data.ByteString) ByteArrayOutputStream(java.io.ByteArrayOutputStream) CountDownLatch(java.util.concurrent.CountDownLatch) TimeoutException(java.util.concurrent.TimeoutException) IOException(java.io.IOException) InvocationOnMock(org.mockito.invocation.InvocationOnMock) Test(org.testng.annotations.Test)

Example 4 with WriteHandle

use of com.linkedin.r2.message.stream.entitystream.WriteHandle in project rest.li by linkedin.

the class TestMIMEInputStream method testExceptionDataSources.

@Test(dataProvider = "exceptionDataSources")
public void testExceptionDataSources(final ExceptionThrowingByteArrayInputStream exceptionThrowingByteArrayInputStream, final int expectedTotalWrites, final int expectedWriteHandleRemainingCalls, final byte[] expectedDataWritten) {
    // Setup:
    final WriteHandle writeHandle = Mockito.mock(WriteHandle.class);
    final MultiPartMIMEInputStream multiPartMIMEInputStream = new MultiPartMIMEInputStream.Builder(exceptionThrowingByteArrayInputStream, _scheduledExecutorService, Collections.<String, String>emptyMap()).withWriteChunkSize(TEST_CHUNK_SIZE).build();
    // Doesn't matter what we return here as long as its constant and above 0.
    when(writeHandle.remaining()).thenReturn(500);
    final ByteArrayOutputStream byteArrayOutputStream = setupMockWriteHandleToOutputStream(writeHandle);
    // Setup for error()
    final CountDownLatch errorLatch = new CountDownLatch(1);
    doAnswer(new Answer<Object>() {

        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            errorLatch.countDown();
            return null;
        }
    }).when(writeHandle).error(isA(Throwable.class));
    // /////////////////////////////////
    // Start things off
    // Init the data source
    multiPartMIMEInputStream.onInit(writeHandle);
    multiPartMIMEInputStream.onWritePossible();
    // Wait to finish
    try {
        boolean successful = errorLatch.await(_testTimeout, TimeUnit.MILLISECONDS);
        if (!successful) {
            Assert.fail("Timeout when waiting for input stream to completely transfer");
        }
    } catch (Exception exception) {
        Assert.fail("Unexpected exception when waiting for input stream to transfer");
    }
    // /////////////////////////////////
    // Assert
    Assert.assertEquals(byteArrayOutputStream.toByteArray(), expectedDataWritten, "Partial data should have been transferred in the case of an exception");
    Assert.assertEquals(exceptionThrowingByteArrayInputStream.isClosed(), true);
    // Mock verifies:
    verify(writeHandle, times(expectedTotalWrites)).write(isA(ByteString.class));
    verify(writeHandle, times(expectedWriteHandleRemainingCalls)).remaining();
    // Since we can't override equals
    verify(writeHandle, times(1)).error(isA(IOException.class));
    verify(writeHandle, never()).done();
    verifyNoMoreInteractions(writeHandle);
}
Also used : WriteHandle(com.linkedin.r2.message.stream.entitystream.WriteHandle) ByteString(com.linkedin.data.ByteString) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) CountDownLatch(java.util.concurrent.CountDownLatch) TimeoutException(java.util.concurrent.TimeoutException) IOException(java.io.IOException) InvocationOnMock(org.mockito.invocation.InvocationOnMock) Test(org.testng.annotations.Test)

Example 5 with WriteHandle

use of com.linkedin.r2.message.stream.entitystream.WriteHandle in project rest.li by linkedin.

the class TestMIMEInputStream method testDifferentDataSourceSizes.

@Test(dataProvider = "differentDataSourceSizes")
public void testDifferentDataSourceSizes(final byte[] inputData, final StrictByteArrayInputStream inputStream, final int writesRemainingPerOnWritePossibles, final int expectedWriteHandleRemaining, final int expectedTotalWrites) {
    // Setup:
    final WriteHandle writeHandle = Mockito.mock(WriteHandle.class);
    final MultiPartMIMEInputStream multiPartMIMEInputStream = new MultiPartMIMEInputStream.Builder(inputStream, _scheduledExecutorService, Collections.<String, String>emptyMap()).withWriteChunkSize(TEST_CHUNK_SIZE).build();
    // Simulate a write handle that offers decreasing writeHandle.remaining()
    final Integer[] remainingWriteHandleCount = simulateDecreasingWriteHandleCount(writesRemainingPerOnWritePossibles);
    when(writeHandle.remaining()).thenReturn(writesRemainingPerOnWritePossibles, remainingWriteHandleCount);
    final ByteArrayOutputStream byteArrayOutputStream = setupMockWriteHandleToOutputStream(writeHandle);
    // Setup for done()
    final CountDownLatch doneLatch = new CountDownLatch(1);
    doAnswer(new Answer<Object>() {

        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            doneLatch.countDown();
            return null;
        }
    }).when(writeHandle).done();
    // /////////////////////////////////
    // Start things off
    // Init the data source
    multiPartMIMEInputStream.onInit(writeHandle);
    multiPartMIMEInputStream.onWritePossible();
    // Wait to finish
    try {
        boolean successful = doneLatch.await(_testTimeout, TimeUnit.MILLISECONDS);
        if (!successful) {
            Assert.fail("Timeout when waiting for input stream to completely transfer");
        }
    } catch (Exception exception) {
        Assert.fail("Unexpected exception when waiting for input stream to completely transfer");
    }
    // /////////////////////////////////
    // Assert
    Assert.assertEquals(byteArrayOutputStream.toByteArray(), inputData, "All data from the input stream should have successfully been transferred");
    Assert.assertEquals(inputStream.isClosed(), true);
    // Mock verifies:
    verify(writeHandle, times(expectedTotalWrites)).write(isA(ByteString.class));
    verify(writeHandle, times(expectedWriteHandleRemaining)).remaining();
    verify(writeHandle, never()).error(isA(Throwable.class));
    verify(writeHandle, times(1)).done();
    verifyNoMoreInteractions(writeHandle);
}
Also used : WriteHandle(com.linkedin.r2.message.stream.entitystream.WriteHandle) ByteString(com.linkedin.data.ByteString) ByteArrayOutputStream(java.io.ByteArrayOutputStream) CountDownLatch(java.util.concurrent.CountDownLatch) TimeoutException(java.util.concurrent.TimeoutException) IOException(java.io.IOException) InvocationOnMock(org.mockito.invocation.InvocationOnMock) Test(org.testng.annotations.Test)

Aggregations

WriteHandle (com.linkedin.r2.message.stream.entitystream.WriteHandle)13 Test (org.testng.annotations.Test)12 CountDownLatch (java.util.concurrent.CountDownLatch)10 ByteString (com.linkedin.data.ByteString)9 IOException (java.io.IOException)8 TimeoutException (java.util.concurrent.TimeoutException)8 InvocationOnMock (org.mockito.invocation.InvocationOnMock)7 ByteArrayOutputStream (java.io.ByteArrayOutputStream)6 EntityStream (com.linkedin.r2.message.stream.entitystream.EntityStream)3 StreamRequest (com.linkedin.r2.message.stream.StreamRequest)2 StreamRequestBuilder (com.linkedin.r2.message.stream.StreamRequestBuilder)2 StreamResponse (com.linkedin.r2.message.stream.StreamResponse)2 ReadHandle (com.linkedin.r2.message.stream.entitystream.ReadHandle)2 Writer (com.linkedin.r2.message.stream.entitystream.Writer)2 ExecutorService (java.util.concurrent.ExecutorService)2 ScheduledExecutorService (java.util.concurrent.ScheduledExecutorService)2 ReplaceableFilter (com.linkedin.r2.caprep.ReplaceableFilter)1 FilterChain (com.linkedin.r2.filter.FilterChain)1 RequestContext (com.linkedin.r2.message.RequestContext)1 RestException (com.linkedin.r2.message.rest.RestException)1