Search in sources :

Example 61 with ByteString

use of com.linkedin.data.ByteString in project rest.li by linkedin.

the class TestMIMEReaderClientCallbackExceptions method testMultiPartMIMEReaderCallbackExceptionOnDrainComplete.

@Test(dataProvider = "allTypesOfBodiesDataSource")
public void testMultiPartMIMEReaderCallbackExceptionOnDrainComplete(final int chunkSize, final List<MimeBodyPart> bodyPartList) throws Exception {
    MimeMultipart multiPartMimeBody = new MimeMultipart();
    // Add your body parts
    for (final MimeBodyPart bodyPart : bodyPartList) {
        multiPartMimeBody.addBodyPart(bodyPart);
    }
    final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    multiPartMimeBody.writeTo(byteArrayOutputStream);
    final ByteString requestPayload = ByteString.copy(byteArrayOutputStream.toByteArray());
    final CountDownLatch countDownLatch = executeRequestPartialReadWithException(requestPayload, chunkSize, multiPartMimeBody.getContentType(), MultiPartMIMEThrowOnFlag.THROW_ON_DRAIN_COMPLETE, SinglePartMIMEThrowOnFlag.NO_THROW);
    countDownLatch.await(_testTimeout, TimeUnit.MILLISECONDS);
    Assert.assertTrue(_currentMultiPartMIMEReaderCallback.getStreamError() instanceof IllegalMonitorStateException);
    Assert.assertEquals(_currentMultiPartMIMEReaderCallback.getSinglePartMIMEReaderCallbacks().size(), 0);
    // Verify this is unusable.
    try {
        _currentMultiPartMIMEReaderCallback.getReader().drainAllParts();
        Assert.fail();
    } catch (MultiPartReaderFinishedException multiPartReaderFinishedException) {
    // pass
    }
}
Also used : MultiPartReaderFinishedException(com.linkedin.multipart.exceptions.MultiPartReaderFinishedException) MimeMultipart(javax.mail.internet.MimeMultipart) ByteString(com.linkedin.data.ByteString) ByteArrayOutputStream(java.io.ByteArrayOutputStream) MimeBodyPart(javax.mail.internet.MimeBodyPart) CountDownLatch(java.util.concurrent.CountDownLatch) Test(org.testng.annotations.Test)

Example 62 with ByteString

use of com.linkedin.data.ByteString in project rest.li by linkedin.

the class TestMIMEReaderClientCallbackExceptions method testSinglePartMIMEReaderCallbackExceptionOnPartDataAvailable.

// /////////////////////////////////////////////////////////////////////////////////////
// SinglePartMIMEReader callback invocations throwing exceptions:
// These tests all verify the resilience of the single part mime reader when single part mime reader client callbacks throw runtime exceptions
@Test(dataProvider = "allTypesOfBodiesDataSource")
public void testSinglePartMIMEReaderCallbackExceptionOnPartDataAvailable(final int chunkSize, final List<MimeBodyPart> bodyPartList) throws Exception {
    MimeMultipart multiPartMimeBody = new MimeMultipart();
    // Add your body parts
    for (final MimeBodyPart bodyPart : bodyPartList) {
        multiPartMimeBody.addBodyPart(bodyPart);
    }
    final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    multiPartMimeBody.writeTo(byteArrayOutputStream);
    final ByteString requestPayload = ByteString.copy(byteArrayOutputStream.toByteArray());
    final CountDownLatch countDownLatch = executeRequestPartialReadWithException(requestPayload, chunkSize, multiPartMimeBody.getContentType(), MultiPartMIMEThrowOnFlag.NO_THROW, SinglePartMIMEThrowOnFlag.THROW_ON_PART_DATA_AVAILABLE);
    countDownLatch.await(_testTimeout, TimeUnit.MILLISECONDS);
    Assert.assertTrue(_currentMultiPartMIMEReaderCallback.getStreamError() instanceof IllegalMonitorStateException);
    // Verify this is unusable.
    try {
        _currentMultiPartMIMEReaderCallback.getReader().drainAllParts();
        Assert.fail();
    } catch (MultiPartReaderFinishedException multiPartReaderFinishedException) {
    // pass
    }
    Assert.assertEquals(_currentMultiPartMIMEReaderCallback.getSinglePartMIMEReaderCallbacks().size(), 1);
    Assert.assertTrue(_currentMultiPartMIMEReaderCallback.getSinglePartMIMEReaderCallbacks().get(0).getStreamError() instanceof IllegalMonitorStateException);
    try {
        _currentMultiPartMIMEReaderCallback.getSinglePartMIMEReaderCallbacks().get(0).getSinglePartMIMEReader().requestPartData();
        Assert.fail();
    } catch (SinglePartFinishedException singlePartFinishedException) {
    // pass
    }
}
Also used : MultiPartReaderFinishedException(com.linkedin.multipart.exceptions.MultiPartReaderFinishedException) MimeMultipart(javax.mail.internet.MimeMultipart) ByteString(com.linkedin.data.ByteString) ByteArrayOutputStream(java.io.ByteArrayOutputStream) MimeBodyPart(javax.mail.internet.MimeBodyPart) CountDownLatch(java.util.concurrent.CountDownLatch) SinglePartFinishedException(com.linkedin.multipart.exceptions.SinglePartFinishedException) Test(org.testng.annotations.Test)

Example 63 with ByteString

use of com.linkedin.data.ByteString in project rest.li by linkedin.

the class TestMIMEReaderExceptions method boundaryPrematurelyTerminatedNoSubsequentCRLFs.

@Test(dataProvider = "multiplePartsDataSource")
public void boundaryPrematurelyTerminatedNoSubsequentCRLFs(final int chunkSize, final List<MimeBodyPart> bodyPartList) throws Exception {
    MimeMultipart multiPartMimeBody = new MimeMultipart();
    // Add your body parts
    for (final MimeBodyPart bodyPart : bodyPartList) {
        multiPartMimeBody.addBodyPart(bodyPart);
    }
    final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    multiPartMimeBody.writeTo(byteArrayOutputStream);
    final byte[] mimePayload = byteArrayOutputStream.toByteArray();
    // At this point the mimePayload's ending looks something like the following. Consider that
    // --1234 is the boundary:
    // <ending of some part data>--1234--/r/n
    // What we want to test this particular code path is:
    // <ending of some part data>--1234678
    // So we trim off an element in the array at the end which results in:
    // <ending of some part data>--1234--/r
    // And then we modify the last three bytes to end up with:
    // <ending of some part data>--1234678
    final byte[] trimmedMimePayload = Arrays.copyOf(mimePayload, mimePayload.length - 1);
    trimmedMimePayload[trimmedMimePayload.length - 1] = 8;
    trimmedMimePayload[trimmedMimePayload.length - 2] = 7;
    trimmedMimePayload[trimmedMimePayload.length - 3] = 6;
    final ByteString requestPayload = ByteString.copy(trimmedMimePayload);
    executeRequestWithDesiredException(requestPayload, chunkSize, multiPartMimeBody.getContentType(), "Malformed multipart mime request. Premature termination of multipart " + "mime body due to a boundary without a subsequent consecutive CRLF.");
    // In this case we want all the parts to still make it over
    List<SinglePartMIMEExceptionReaderCallbackImpl> singlePartMIMEReaderCallbacks = _currentMultiPartMIMEReaderCallback.getSinglePartMIMEReaderCallbacks();
    Assert.assertEquals(singlePartMIMEReaderCallbacks.size(), multiPartMimeBody.getCount());
    // Everything should have made it over
    for (int i = 0; i < singlePartMIMEReaderCallbacks.size(); i++) {
        // Actual
        final SinglePartMIMEExceptionReaderCallbackImpl currentCallback = singlePartMIMEReaderCallbacks.get(i);
        // Expected
        final BodyPart currentExpectedPart = multiPartMimeBody.getBodyPart(i);
        // Construct expected headers and verify they match
        final Map<String, String> expectedHeaders = new HashMap<>();
        @SuppressWarnings("unchecked") final Enumeration<Header> allHeaders = currentExpectedPart.getAllHeaders();
        while (allHeaders.hasMoreElements()) {
            final Header header = allHeaders.nextElement();
            expectedHeaders.put(header.getName(), header.getValue());
        }
        Assert.assertEquals(currentCallback.getHeaders(), expectedHeaders);
        // Verify the body matches
        Assert.assertNotNull(currentCallback.getFinishedData());
        if (currentExpectedPart.getContent() instanceof byte[]) {
            Assert.assertEquals(currentCallback.getFinishedData().copyBytes(), currentExpectedPart.getContent());
        } else {
            // Default is String
            Assert.assertEquals(new String(currentCallback.getFinishedData().copyBytes()), currentExpectedPart.getContent());
        }
    }
}
Also used : MimeBodyPart(javax.mail.internet.MimeBodyPart) BodyPart(javax.mail.BodyPart) HashMap(java.util.HashMap) ByteString(com.linkedin.data.ByteString) ByteArrayOutputStream(java.io.ByteArrayOutputStream) ByteString(com.linkedin.data.ByteString) Header(javax.mail.Header) MimeMultipart(javax.mail.internet.MimeMultipart) MimeBodyPart(javax.mail.internet.MimeBodyPart) Test(org.testng.annotations.Test)

Example 64 with ByteString

use of com.linkedin.data.ByteString in project rest.li by linkedin.

the class AbstractMIMEUnitTest method mockR2AndWrite.

// This is used when we need to mock out R2 and write a payload for our reader to read
protected void mockR2AndWrite(final ByteString payload, final int chunkSize, final String contentType) {
    _entityStream = mock(EntityStream.class);
    _readHandle = mock(ReadHandle.class);
    _streamRequest = mock(StreamRequest.class);
    // We have to use the AtomicReference holder technique to modify the current remaining buffer since the inner class
    // in doAnswer() can only access final variables.
    final AtomicReference<MultiPartMIMEReader.R2MultiPartMIMEReader> r2Reader = new AtomicReference<>();
    // This takes the place of VariableByteStringWriter if we were to use R2 directly.
    final VariableByteStringViewer variableByteStringViewer = new VariableByteStringViewer(payload, chunkSize);
    // When data is requested, we write
    doAnswer(new Answer<Object>() {

        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            final MultiPartMIMEReader.R2MultiPartMIMEReader reader = r2Reader.get();
            Object[] args = invocation.getArguments();
            // will always be 1 since MultiPartMIMEReader only does _rh.request(1)
            final int chunksRequested = (Integer) args[0];
            for (int i = 0; i < chunksRequested; i++) {
                // Our tests will run into a stack overflow unless we use a thread pool here to fire off the callbacks.
                // Especially in cases where the chunk size is 1. When the chunk size is one, the MultiPartMIMEReader
                // ends up doing many _rh.request(1) since each write is only 1 byte.
                // R2 uses a different technique to avoid stack overflows here which is unnecessary to emulate.
                _scheduledExecutorService.submit(new Runnable() {

                    @Override
                    public void run() {
                        ByteString clientData = variableByteStringViewer.onWritePossible();
                        if (clientData.equals(ByteString.empty())) {
                            reader.onDone();
                        } else {
                            reader.onDataAvailable(clientData);
                        }
                    }
                });
            }
            return null;
        }
    }).when(_readHandle).request(isA(Integer.class));
    // We need a final version of the read handle since its passed to an inner class below.
    final ReadHandle readHandleRef = _readHandle;
    doAnswer(new Answer<Object>() {

        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {
            Object[] args = invocation.getArguments();
            final MultiPartMIMEReader.R2MultiPartMIMEReader reader = (MultiPartMIMEReader.R2MultiPartMIMEReader) args[0];
            r2Reader.set(reader);
            // R2 calls init immediately upon setting the reader
            reader.onInit(readHandleRef);
            return null;
        }
    }).when(_entityStream).setReader(isA(MultiPartMIMEReader.R2MultiPartMIMEReader.class));
    when(_streamRequest.getEntityStream()).thenReturn(_entityStream);
    final String contentTypeHeader = contentType + ";somecustomparameter=somecustomvalue" + ";anothercustomparameter=anothercustomvalue";
    when(_streamRequest.getHeader(MultiPartMIMEUtils.CONTENT_TYPE_HEADER)).thenReturn(contentTypeHeader);
}
Also used : ByteString(com.linkedin.data.ByteString) AtomicReference(java.util.concurrent.atomic.AtomicReference) ByteString(com.linkedin.data.ByteString) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) EntityStream(com.linkedin.r2.message.stream.entitystream.EntityStream) ReadHandle(com.linkedin.r2.message.stream.entitystream.ReadHandle) VariableByteStringViewer(com.linkedin.multipart.utils.VariableByteStringViewer) InvocationOnMock(org.mockito.invocation.InvocationOnMock)

Example 65 with ByteString

use of com.linkedin.data.ByteString in project rest.li by linkedin.

the class MultiPartMIMEChainReaderCallback method onNewDataSource.

@Override
public void onNewDataSource(final MultiPartMIMEDataSourceWriter multiPartMIMEDataSourceWriter) {
    multiPartMIMEDataSourceWriter.onInit(new WriteHandle() {

        @Override
        public void write(ByteString data) {
            _writeHandle.write(data);
        }

        @Override
        public void done() {
        // We intentionally ignore this, since we will be responsible for calling writeHandle.done() when all the data
        // sources represented by the MultiPartMIMEDataSourceIterator have finished.
        }

        @Override
        public void error(Throwable throwable) {
            _writeHandle.error(throwable);
        }

        @Override
        public int remaining() {
            return _writeHandle.remaining();
        }
    });
    _currentDataSource = multiPartMIMEDataSourceWriter;
    ByteString serializedBoundaryAndHeaders = null;
    try {
        serializedBoundaryAndHeaders = MultiPartMIMEUtils.serializeBoundaryAndHeaders(_normalEncapsulationBoundary, multiPartMIMEDataSourceWriter);
    } catch (IOException ioException) {
        // Should never happen
        onStreamError(ioException);
    }
    _writeHandle.write(serializedBoundaryAndHeaders);
    if (_writeHandle.remaining() > 0) {
        multiPartMIMEDataSourceWriter.onWritePossible();
    }
}
Also used : WriteHandle(com.linkedin.r2.message.stream.entitystream.WriteHandle) ByteString(com.linkedin.data.ByteString) IOException(java.io.IOException)

Aggregations

ByteString (com.linkedin.data.ByteString)152 Test (org.testng.annotations.Test)77 ByteArrayOutputStream (java.io.ByteArrayOutputStream)33 MimeMultipart (javax.mail.internet.MimeMultipart)31 MimeBodyPart (javax.mail.internet.MimeBodyPart)26 DataMap (com.linkedin.data.DataMap)25 RestResponse (com.linkedin.r2.message.rest.RestResponse)25 StreamResponse (com.linkedin.r2.message.stream.StreamResponse)22 FullEntityReader (com.linkedin.r2.message.stream.entitystream.FullEntityReader)22 RestRequest (com.linkedin.r2.message.rest.RestRequest)21 StreamRequest (com.linkedin.r2.message.stream.StreamRequest)21 URI (java.net.URI)21 CountDownLatch (java.util.concurrent.CountDownLatch)20 RequestContext (com.linkedin.r2.message.RequestContext)18 RestRequestBuilder (com.linkedin.r2.message.rest.RestRequestBuilder)18 Callback (com.linkedin.common.callback.Callback)17 StreamRequestBuilder (com.linkedin.r2.message.stream.StreamRequestBuilder)14 RestException (com.linkedin.r2.message.rest.RestException)12 HashMap (java.util.HashMap)12 DataList (com.linkedin.data.DataList)11