Search in sources :

Example 6 with Http2Runnable

use of io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable in project netty by netty.

the class Http2ConnectionRoundtripTest method setGracefulShutdownTime.

private static void setGracefulShutdownTime(Channel channel, final Http2ConnectionHandler handler, final long millis) throws InterruptedException {
    final CountDownLatch latch = new CountDownLatch(1);
    runInChannel(channel, new Http2Runnable() {

        @Override
        public void run() throws Http2Exception {
            handler.gracefulShutdownTimeoutMillis(millis);
            latch.countDown();
        }
    });
    assertTrue(latch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
}
Also used : Http2Runnable(io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable) CountDownLatch(java.util.concurrent.CountDownLatch)

Example 7 with Http2Runnable

use of io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable in project netty by netty.

the class Http2ConnectionRoundtripTest method listenerExceptionShouldCloseConnection.

@Test
public void listenerExceptionShouldCloseConnection() throws Exception {
    final Http2Headers headers = dummyHeaders();
    doThrow(new RuntimeException("Fake Exception")).when(serverListener).onHeadersRead(any(ChannelHandlerContext.class), eq(3), eq(headers), eq(0), eq((short) 16), eq(false), eq(0), eq(false));
    bootstrapEnv(1, 0, 1, 1);
    // Create a latch to track when the close occurs.
    final CountDownLatch closeLatch = new CountDownLatch(1);
    clientChannel.closeFuture().addListener(new ChannelFutureListener() {

        @Override
        public void operationComplete(ChannelFuture future) throws Exception {
            closeLatch.countDown();
        }
    });
    // Create a single stream by sending a HEADERS frame to the server.
    runInChannel(clientChannel, new Http2Runnable() {

        @Override
        public void run() throws Http2Exception {
            http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, (short) 16, false, 0, false, newPromise());
            http2Client.flush(ctx());
        }
    });
    // Wait for the server to create the stream.
    assertTrue(serverSettingsAckLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
    assertTrue(requestLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
    // Wait for the close to occur.
    assertTrue(closeLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
    assertFalse(clientChannel.isOpen());
}
Also used : ChannelFuture(io.netty.channel.ChannelFuture) Http2Runnable(io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) CountDownLatch(java.util.concurrent.CountDownLatch) ChannelFutureListener(io.netty.channel.ChannelFutureListener) IllegalReferenceCountException(io.netty.util.IllegalReferenceCountException) ExecutionException(java.util.concurrent.ExecutionException) Test(org.junit.jupiter.api.Test)

Example 8 with Http2Runnable

use of io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable in project netty by netty.

the class Http2ConnectionRoundtripTest method stressTest.

@Test
public void stressTest() throws Exception {
    final Http2Headers headers = dummyHeaders();
    int length = 10;
    final ByteBuf data = randomBytes(length);
    final String dataAsHex = ByteBufUtil.hexDump(data);
    final long pingData = 8;
    final int numStreams = 2000;
    // Collect all the ping buffers as we receive them at the server.
    final long[] receivedPings = new long[numStreams];
    doAnswer(new Answer<Void>() {

        int nextIndex;

        @Override
        public Void answer(InvocationOnMock in) throws Throwable {
            receivedPings[nextIndex++] = (Long) in.getArguments()[1];
            return null;
        }
    }).when(serverListener).onPingRead(any(ChannelHandlerContext.class), any(Long.class));
    // Collect all the data buffers as we receive them at the server.
    final StringBuilder[] receivedData = new StringBuilder[numStreams];
    doAnswer(new Answer<Integer>() {

        @Override
        public Integer answer(InvocationOnMock in) throws Throwable {
            int streamId = (Integer) in.getArguments()[1];
            ByteBuf buf = (ByteBuf) in.getArguments()[2];
            int padding = (Integer) in.getArguments()[3];
            int processedBytes = buf.readableBytes() + padding;
            int streamIndex = (streamId - 3) / 2;
            StringBuilder builder = receivedData[streamIndex];
            if (builder == null) {
                builder = new StringBuilder(dataAsHex.length());
                receivedData[streamIndex] = builder;
            }
            builder.append(ByteBufUtil.hexDump(buf));
            return processedBytes;
        }
    }).when(serverListener).onDataRead(any(ChannelHandlerContext.class), anyInt(), any(ByteBuf.class), anyInt(), anyBoolean());
    try {
        bootstrapEnv(numStreams * length, 1, numStreams * 4, numStreams);
        runInChannel(clientChannel, new Http2Runnable() {

            @Override
            public void run() throws Http2Exception {
                int upperLimit = 3 + 2 * numStreams;
                for (int streamId = 3; streamId < upperLimit; streamId += 2) {
                    // Send a bunch of data on each stream.
                    http2Client.encoder().writeHeaders(ctx(), streamId, headers, 0, (short) 16, false, 0, false, newPromise());
                    http2Client.encoder().writePing(ctx(), false, pingData, newPromise());
                    http2Client.encoder().writeData(ctx(), streamId, data.retainedSlice(), 0, false, newPromise());
                    // Write trailers.
                    http2Client.encoder().writeHeaders(ctx(), streamId, headers, 0, (short) 16, false, 0, true, newPromise());
                    http2Client.flush(ctx());
                }
            }
        });
        // Wait for all frames to be received.
        assertTrue(serverSettingsAckLatch.await(60, SECONDS));
        assertTrue(trailersLatch.await(60, SECONDS));
        verify(serverListener, times(numStreams)).onHeadersRead(any(ChannelHandlerContext.class), anyInt(), eq(headers), eq(0), eq((short) 16), eq(false), eq(0), eq(false));
        verify(serverListener, times(numStreams)).onHeadersRead(any(ChannelHandlerContext.class), anyInt(), eq(headers), eq(0), eq((short) 16), eq(false), eq(0), eq(true));
        verify(serverListener, times(numStreams)).onPingRead(any(ChannelHandlerContext.class), any(long.class));
        verify(serverListener, never()).onDataRead(any(ChannelHandlerContext.class), anyInt(), any(ByteBuf.class), eq(0), eq(true));
        for (StringBuilder builder : receivedData) {
            assertEquals(dataAsHex, builder.toString());
        }
        for (long receivedPing : receivedPings) {
            assertEquals(pingData, receivedPing);
        }
    } finally {
        // Don't wait for server to close streams
        setClientGracefulShutdownTime(0);
        data.release();
    }
}
Also used : Http2Runnable(io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) AsciiString(io.netty.util.AsciiString) Http2TestUtil.randomString(io.netty.handler.codec.http2.Http2TestUtil.randomString) ByteBuf(io.netty.buffer.ByteBuf) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) InvocationOnMock(org.mockito.invocation.InvocationOnMock) Mockito.anyLong(org.mockito.Mockito.anyLong) Test(org.junit.jupiter.api.Test)

Example 9 with Http2Runnable

use of io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable in project netty by netty.

the class Http2ConnectionRoundtripTest method encodeViolatesMaxHeaderListSizeCanStillUseConnection.

@Test
public void encodeViolatesMaxHeaderListSizeCanStillUseConnection() throws Exception {
    bootstrapEnv(1, 2, 1, 0, 0);
    final CountDownLatch serverSettingsAckLatch1 = new CountDownLatch(2);
    final CountDownLatch serverSettingsAckLatch2 = new CountDownLatch(3);
    final CountDownLatch clientSettingsLatch1 = new CountDownLatch(3);
    final CountDownLatch serverRevHeadersLatch = new CountDownLatch(1);
    final CountDownLatch clientHeadersLatch = new CountDownLatch(1);
    final CountDownLatch clientDataWrite = new CountDownLatch(1);
    final AtomicReference<Throwable> clientHeadersWriteException = new AtomicReference<Throwable>();
    final AtomicReference<Throwable> clientHeadersWriteException2 = new AtomicReference<Throwable>();
    final AtomicReference<Throwable> clientDataWriteException = new AtomicReference<Throwable>();
    final Http2Headers headers = dummyHeaders();
    doAnswer(new Answer<Void>() {

        @Override
        public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
            serverSettingsAckLatch1.countDown();
            serverSettingsAckLatch2.countDown();
            return null;
        }
    }).when(serverListener).onSettingsAckRead(any(ChannelHandlerContext.class));
    doAnswer(new Answer<Void>() {

        @Override
        public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
            clientSettingsLatch1.countDown();
            return null;
        }
    }).when(clientListener).onSettingsRead(any(ChannelHandlerContext.class), any(Http2Settings.class));
    // Manually add a listener for when we receive the expected headers on the server.
    doAnswer(new Answer<Void>() {

        @Override
        public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
            serverRevHeadersLatch.countDown();
            return null;
        }
    }).when(serverListener).onHeadersRead(any(ChannelHandlerContext.class), eq(5), eq(headers), anyInt(), anyShort(), anyBoolean(), eq(0), eq(true));
    // Set the maxHeaderListSize to 100 so we may be able to write some headers, but not all. We want to verify
    // that we don't corrupt state if some can be written but not all.
    runInChannel(serverConnectedChannel, new Http2Runnable() {

        @Override
        public void run() throws Http2Exception {
            http2Server.encoder().writeSettings(serverCtx(), new Http2Settings().copyFrom(http2Server.decoder().localSettings()).maxHeaderListSize(100), serverNewPromise());
            http2Server.flush(serverCtx());
        }
    });
    assertTrue(serverSettingsAckLatch1.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
    runInChannel(clientChannel, new Http2Runnable() {

        @Override
        public void run() throws Http2Exception {
            http2Client.encoder().writeHeaders(ctx(), 3, headers, 0, false, newPromise()).addListener(new ChannelFutureListener() {

                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    clientHeadersWriteException.set(future.cause());
                }
            });
            // It is expected that this write should fail locally and the remote peer will never see this.
            http2Client.encoder().writeData(ctx(), 3, Unpooled.buffer(), 0, true, newPromise()).addListener(new ChannelFutureListener() {

                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    clientDataWriteException.set(future.cause());
                    clientDataWrite.countDown();
                }
            });
            http2Client.flush(ctx());
        }
    });
    assertTrue(clientDataWrite.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
    assertNotNull(clientHeadersWriteException.get(), "Header encode should have exceeded maxHeaderListSize!");
    assertNotNull(clientDataWriteException.get(), "Data on closed stream should fail!");
    // Set the maxHeaderListSize to the max value so we can send the headers.
    runInChannel(serverConnectedChannel, new Http2Runnable() {

        @Override
        public void run() throws Http2Exception {
            http2Server.encoder().writeSettings(serverCtx(), new Http2Settings().copyFrom(http2Server.decoder().localSettings()).maxHeaderListSize(Http2CodecUtil.MAX_HEADER_LIST_SIZE), serverNewPromise());
            http2Server.flush(serverCtx());
        }
    });
    assertTrue(clientSettingsLatch1.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
    assertTrue(serverSettingsAckLatch2.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
    runInChannel(clientChannel, new Http2Runnable() {

        @Override
        public void run() throws Http2Exception {
            http2Client.encoder().writeHeaders(ctx(), 5, headers, 0, true, newPromise()).addListener(new ChannelFutureListener() {

                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    clientHeadersWriteException2.set(future.cause());
                    clientHeadersLatch.countDown();
                }
            });
            http2Client.flush(ctx());
        }
    });
    assertTrue(clientHeadersLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
    assertNull(clientHeadersWriteException2.get(), "Client write of headers should succeed with increased header list size!");
    assertTrue(serverRevHeadersLatch.await(DEFAULT_AWAIT_TIMEOUT_SECONDS, SECONDS));
    verify(serverListener, never()).onDataRead(any(ChannelHandlerContext.class), anyInt(), any(ByteBuf.class), anyInt(), anyBoolean());
    // Verify that no errors have been received.
    verify(serverListener, never()).onGoAwayRead(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class));
    verify(serverListener, never()).onRstStreamRead(any(ChannelHandlerContext.class), anyInt(), anyLong());
    verify(clientListener, never()).onGoAwayRead(any(ChannelHandlerContext.class), anyInt(), anyLong(), any(ByteBuf.class));
    verify(clientListener, never()).onRstStreamRead(any(ChannelHandlerContext.class), anyInt(), anyLong());
}
Also used : ChannelFuture(io.netty.channel.ChannelFuture) Http2Runnable(io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable) AtomicReference(java.util.concurrent.atomic.AtomicReference) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) CountDownLatch(java.util.concurrent.CountDownLatch) ByteBuf(io.netty.buffer.ByteBuf) ChannelFutureListener(io.netty.channel.ChannelFutureListener) InvocationOnMock(org.mockito.invocation.InvocationOnMock) Test(org.junit.jupiter.api.Test)

Example 10 with Http2Runnable

use of io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable in project netty by netty.

the class Http2ConnectionRoundtripTest method writeOfEmptyReleasedBufferQueuedInFlowControllerShouldFail.

private void writeOfEmptyReleasedBufferQueuedInFlowControllerShouldFail(final WriteEmptyBufferMode mode) throws Exception {
    bootstrapEnv(1, 1, 2, 1);
    final ChannelPromise emptyDataPromise = newPromise();
    runInChannel(clientChannel, new Http2Runnable() {

        @Override
        public void run() throws Http2Exception {
            http2Client.encoder().writeHeaders(ctx(), 3, EmptyHttp2Headers.INSTANCE, 0, (short) 16, false, 0, false, newPromise());
            ByteBuf emptyBuf = Unpooled.buffer();
            emptyBuf.release();
            switch(mode) {
                case SINGLE_END_OF_STREAM:
                    http2Client.encoder().writeData(ctx(), 3, emptyBuf, 0, true, emptyDataPromise);
                    break;
                case SECOND_END_OF_STREAM:
                    http2Client.encoder().writeData(ctx(), 3, emptyBuf, 0, false, emptyDataPromise);
                    http2Client.encoder().writeData(ctx(), 3, randomBytes(8), 0, true, newPromise());
                    break;
                case SINGLE_WITH_TRAILERS:
                    http2Client.encoder().writeData(ctx(), 3, emptyBuf, 0, false, emptyDataPromise);
                    http2Client.encoder().writeHeaders(ctx(), 3, EmptyHttp2Headers.INSTANCE, 0, (short) 16, false, 0, true, newPromise());
                    break;
                case SECOND_WITH_TRAILERS:
                    http2Client.encoder().writeData(ctx(), 3, emptyBuf, 0, false, emptyDataPromise);
                    http2Client.encoder().writeData(ctx(), 3, randomBytes(8), 0, false, newPromise());
                    http2Client.encoder().writeHeaders(ctx(), 3, EmptyHttp2Headers.INSTANCE, 0, (short) 16, false, 0, true, newPromise());
                    break;
                default:
                    throw new Error();
            }
            http2Client.flush(ctx());
        }
    });
    ExecutionException e = assertThrows(ExecutionException.class, new Executable() {

        @Override
        public void execute() throws Throwable {
            emptyDataPromise.get();
        }
    });
    assertThat(e.getCause(), is(instanceOf(IllegalReferenceCountException.class)));
}
Also used : Http2Runnable(io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable) ChannelPromise(io.netty.channel.ChannelPromise) ByteBuf(io.netty.buffer.ByteBuf) ExecutionException(java.util.concurrent.ExecutionException) Executable(org.junit.jupiter.api.function.Executable)

Aggregations

Http2Runnable (io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable)41 Test (org.junit.jupiter.api.Test)37 ByteBuf (io.netty.buffer.ByteBuf)28 AsciiString (io.netty.util.AsciiString)20 ChannelHandlerContext (io.netty.channel.ChannelHandlerContext)18 Http2CodecUtil.getEmbeddedHttp2Exception (io.netty.handler.codec.http2.Http2CodecUtil.getEmbeddedHttp2Exception)12 DefaultFullHttpRequest (io.netty.handler.codec.http.DefaultFullHttpRequest)11 FullHttpMessage (io.netty.handler.codec.http.FullHttpMessage)11 HttpHeaders (io.netty.handler.codec.http.HttpHeaders)11 CountDownLatch (java.util.concurrent.CountDownLatch)11 FullHttpRequest (io.netty.handler.codec.http.FullHttpRequest)9 InvocationOnMock (org.mockito.invocation.InvocationOnMock)9 ChannelFuture (io.netty.channel.ChannelFuture)6 ChannelFutureListener (io.netty.channel.ChannelFutureListener)6 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)6 ExecutionException (java.util.concurrent.ExecutionException)5 AtomicReference (java.util.concurrent.atomic.AtomicReference)4 IllegalReferenceCountException (io.netty.util.IllegalReferenceCountException)3 ChannelHandlerAdapter (io.netty.channel.ChannelHandlerAdapter)2 ChannelPromise (io.netty.channel.ChannelPromise)2