@Test public void testResponseWithContentLength() { EmbeddedChannel ch = new EmbeddedChannel(new HttpResponseDecoder()); ch.writeInbound( Unpooled.copiedBuffer( "HTTP/1.1 200 OK\r\n" + "Content-Length: 10\r\n" + "\r\n", CharsetUtil.US_ASCII)); byte[] data = new byte[10]; for (int i = 0; i < data.length; i++) { data[i] = (byte) i; } ch.writeInbound(Unpooled.wrappedBuffer(data, 0, data.length / 2)); ch.writeInbound(Unpooled.wrappedBuffer(data, 5, data.length / 2)); HttpResponse res = ch.readInbound(); assertThat(res.getProtocolVersion(), sameInstance(HttpVersion.HTTP_1_1)); assertThat(res.getStatus(), is(HttpResponseStatus.OK)); HttpContent firstContent = ch.readInbound(); assertThat(firstContent.content().readableBytes(), is(5)); assertEquals(Unpooled.wrappedBuffer(data, 0, 5), firstContent.content()); firstContent.release(); LastHttpContent lastContent = ch.readInbound(); assertEquals(5, lastContent.content().readableBytes()); assertEquals(Unpooled.wrappedBuffer(data, 5, 5), lastContent.content()); lastContent.release(); assertThat(ch.finish(), is(false)); assertThat(ch.readInbound(), is(nullValue())); }
private static void testSpdySessionHandlerPing(SpdyVersion version, boolean server) { EmbeddedChannel sessionHandler = new EmbeddedChannel( new SpdySessionHandler(version, server), new EchoHandler(closeSignal, server)); while (sessionHandler.readOutbound() != null) { continue; } int localStreamId = server ? 1 : 2; int remoteStreamId = server ? 2 : 1; SpdyPingFrame localPingFrame = new DefaultSpdyPingFrame(localStreamId); SpdyPingFrame remotePingFrame = new DefaultSpdyPingFrame(remoteStreamId); // Check if session handler returns identical local PINGs sessionHandler.writeInbound(localPingFrame); assertPing(sessionHandler.readOutbound(), localPingFrame.getId()); assertNull(sessionHandler.readOutbound()); // Check if session handler ignores un-initiated remote PINGs sessionHandler.writeInbound(remotePingFrame); assertNull(sessionHandler.readOutbound()); sessionHandler.finish(); }
private static void testLastResponseWithTrailingHeaderFragmented( byte[] content, int fragmentSize) { EmbeddedChannel ch = new EmbeddedChannel(new HttpResponseDecoder()); int headerLength = 47; // split up the header for (int a = 0; a < headerLength; ) { int amount = fragmentSize; if (a + amount > headerLength) { amount = headerLength - a; } // if header is done it should produce a HttpRequest boolean headerDone = a + amount == headerLength; assertEquals(headerDone, ch.writeInbound(Unpooled.wrappedBuffer(content, a, amount))); a += amount; } ch.writeInbound(Unpooled.wrappedBuffer(content, headerLength, content.length - headerLength)); HttpResponse res = ch.readInbound(); assertThat(res.getProtocolVersion(), sameInstance(HttpVersion.HTTP_1_1)); assertThat(res.getStatus(), is(HttpResponseStatus.OK)); LastHttpContent lastContent = ch.readInbound(); assertThat(lastContent.content().isReadable(), is(false)); HttpHeaders headers = lastContent.trailingHeaders(); assertEquals(1, headers.names().size()); List<String> values = headers.getAll("Set-Cookie"); assertEquals(2, values.size()); assertTrue(values.contains("t1=t1v1")); assertTrue(values.contains("t2=t2v2; Expires=Wed, 09-Jun-2021 10:18:14 GMT")); lastContent.release(); assertThat(ch.finish(), is(false)); assertThat(ch.readInbound(), is(nullValue())); }
@Test public void testLastResponseWithHeaderRemoveTrailingSpaces() { EmbeddedChannel ch = new EmbeddedChannel(new HttpResponseDecoder()); ch.writeInbound( Unpooled.copiedBuffer( "HTTP/1.1 200 OK\r\nX-Header: h2=h2v2; Expires=Wed, 09-Jun-2021 10:18:14 GMT \r\n\r\n", CharsetUtil.US_ASCII)); HttpResponse res = ch.readInbound(); assertThat(res.getProtocolVersion(), sameInstance(HttpVersion.HTTP_1_1)); assertThat(res.getStatus(), is(HttpResponseStatus.OK)); assertThat(res.headers().get("X-Header"), is("h2=h2v2; Expires=Wed, 09-Jun-2021 10:18:14 GMT")); assertThat(ch.readInbound(), is(nullValue())); ch.writeInbound(Unpooled.wrappedBuffer(new byte[1024])); HttpContent content = ch.readInbound(); assertThat(content.content().readableBytes(), is(1024)); content.release(); assertThat(ch.finish(), is(true)); LastHttpContent lastContent = ch.readInbound(); assertThat(lastContent.content().isReadable(), is(false)); lastContent.release(); assertThat(ch.readInbound(), is(nullValue())); }
@Test public void testGarbageHeaders() { // A response without headers - from https://github.com/netty/netty/issues/2103 byte[] data = ("<html>\r\n" + "<head><title>400 Bad Request</title></head>\r\n" + "<body bgcolor=\"white\">\r\n" + "<center><h1>400 Bad Request</h1></center>\r\n" + "<hr><center>nginx/1.1.19</center>\r\n" + "</body>\r\n" + "</html>\r\n") .getBytes(); EmbeddedChannel ch = new EmbeddedChannel(new HttpResponseDecoder()); ch.writeInbound(Unpooled.wrappedBuffer(data)); // Garbage input should generate the 999 Unknown response. HttpResponse res = ch.readInbound(); assertThat(res.getProtocolVersion(), sameInstance(HttpVersion.HTTP_1_0)); assertThat(res.getStatus().code(), is(999)); assertThat(res.getDecoderResult().isFailure(), is(true)); assertThat(res.getDecoderResult().isFinished(), is(true)); assertThat(ch.readInbound(), is(nullValue())); // More garbage should not generate anything (i.e. the decoder discards anything beyond this // point.) ch.writeInbound(Unpooled.wrappedBuffer(data)); assertThat(ch.readInbound(), is(nullValue())); // Closing the connection should not generate anything since the protocol has been violated. ch.finish(); assertThat(ch.readInbound(), is(nullValue())); }
@AdviseWith(adviceClasses = NettyUtilAdvice.class) @NewEnv(type = NewEnv.Type.CLASSLOADER) @Test public void testExecute() throws Exception { EmbeddedChannel embeddedChannel = NettyTestUtil.createEmptyEmbeddedChannel(); ChannelPipeline channelPipeline = embeddedChannel.pipeline(); channelPipeline.addFirst(NettyRPCChannelHandler.NAME, NettyRPCChannelHandler.INSTANCE); NettyChannelAttributes.putFabricWorker( embeddedChannel, 0, new LocalFabricWorker<Serializable>( new EmbeddedProcessChannel<Serializable>(new DefaultNoticeableFuture<Serializable>()))); ProcessCallableExecutor processCallableExecutor = new NettyFabricWorkerProcessCallableExecutor(embeddedChannel, 0, Long.MAX_VALUE); NoticeableFuture<Serializable> noticeableFuture = processCallableExecutor.execute( new ProcessCallable<Serializable>() { @Override public Serializable call() { return StringPool.BLANK; } }); embeddedChannel.writeInbound(embeddedChannel.readOutbound()); embeddedChannel.writeInbound(embeddedChannel.readOutbound()); Assert.assertEquals(StringPool.BLANK, noticeableFuture.get()); final ProcessException processException = new ProcessException(""); noticeableFuture = processCallableExecutor.execute( new ProcessCallable<Serializable>() { @Override public Serializable call() throws ProcessException { throw processException; } }); embeddedChannel.writeInbound(embeddedChannel.readOutbound()); embeddedChannel.writeInbound(embeddedChannel.readOutbound()); try { noticeableFuture.get(); Assert.fail(); } catch (ExecutionException ee) { Assert.assertSame(processException, ee.getCause()); } }
@Test public void testTinyDecode() { byte[] b = {4, 1, 1, 1, 1}; ch.writeInbound(wrappedBuffer(b, 0, 1)); assertThat(ch.readInbound(), is(nullValue())); ch.writeInbound(wrappedBuffer(b, 1, 2)); assertThat(ch.readInbound(), is(nullValue())); ch.writeInbound(wrappedBuffer(b, 3, b.length - 3)); assertThat( releaseLater((ByteBuf) ch.readInbound()), is(releaseLater(wrappedBuffer(new byte[] {1, 1, 1, 1})))); }
@Test public void testResponseChunkedExceedMaxChunkSize() { EmbeddedChannel ch = new EmbeddedChannel(new HttpResponseDecoder(4096, 8192, 32)); ch.writeInbound( Unpooled.copiedBuffer( "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n", CharsetUtil.US_ASCII)); HttpResponse res = ch.readInbound(); assertThat(res.getProtocolVersion(), sameInstance(HttpVersion.HTTP_1_1)); assertThat(res.getStatus(), is(HttpResponseStatus.OK)); byte[] data = new byte[64]; for (int i = 0; i < data.length; i++) { data[i] = (byte) i; } for (int i = 0; i < 10; i++) { assertFalse( ch.writeInbound( Unpooled.copiedBuffer( Integer.toHexString(data.length) + "\r\n", CharsetUtil.US_ASCII))); assertTrue(ch.writeInbound(Unpooled.wrappedBuffer(data))); byte[] decodedData = new byte[data.length]; HttpContent content = ch.readInbound(); assertEquals(32, content.content().readableBytes()); content.content().readBytes(decodedData, 0, 32); content.release(); content = ch.readInbound(); assertEquals(32, content.content().readableBytes()); content.content().readBytes(decodedData, 32, 32); assertArrayEquals(data, decodedData); content.release(); assertFalse(ch.writeInbound(Unpooled.copiedBuffer("\r\n", CharsetUtil.US_ASCII))); } // Write the last chunk. ch.writeInbound(Unpooled.copiedBuffer("0\r\n\r\n", CharsetUtil.US_ASCII)); // Ensure the last chunk was decoded. LastHttpContent content = ch.readInbound(); assertFalse(content.content().isReadable()); content.release(); ch.finish(); assertNull(ch.readInbound()); }
@Test public void testExecute() throws Exception { EmbeddedChannel embeddedChannel = NettyTestUtil.createEmptyEmbeddedChannel(); ChannelPipeline channelPipeline = embeddedChannel.pipeline(); channelPipeline.addFirst(NettyRPCChannelHandler.NAME, NettyRPCChannelHandler.INSTANCE); ProcessCallableExecutor processCallableExecutor = new NettyFabricAgentProcessCallableExecutor(embeddedChannel); NoticeableFuture<Serializable> noticeableFuture = processCallableExecutor.execute( new ProcessCallable<Serializable>() { @Override public Serializable call() { return StringPool.BLANK; } }); embeddedChannel.writeInbound(embeddedChannel.readOutbound()); embeddedChannel.writeInbound(embeddedChannel.readOutbound()); Assert.assertEquals(StringPool.BLANK, noticeableFuture.get()); final ProcessException processException = new ProcessException(""); noticeableFuture = processCallableExecutor.execute( new ProcessCallable<Serializable>() { @Override public Serializable call() throws ProcessException { throw processException; } }); embeddedChannel.writeInbound(embeddedChannel.readOutbound()); embeddedChannel.writeInbound(embeddedChannel.readOutbound()); try { noticeableFuture.get(); Assert.fail(); } catch (ExecutionException ee) { Assert.assertSame(processException, ee.getCause()); } }
private static void testSpdySessionHandlerGoAway(SpdyVersion version, boolean server) { EmbeddedChannel sessionHandler = new EmbeddedChannel( new SpdySessionHandler(version, server), new EchoHandler(closeSignal, server)); while (sessionHandler.readOutbound() != null) { continue; } int localStreamId = server ? 1 : 2; SpdySynStreamFrame spdySynStreamFrame = new DefaultSpdySynStreamFrame(localStreamId, 0, (byte) 0); spdySynStreamFrame.headers().set("Compression", "test"); SpdyDataFrame spdyDataFrame = new DefaultSpdyDataFrame(localStreamId); spdyDataFrame.setLast(true); // Send an initial request sessionHandler.writeInbound(spdySynStreamFrame); assertSynReply( sessionHandler.readOutbound(), localStreamId, false, spdySynStreamFrame.headers()); assertNull(sessionHandler.readOutbound()); sessionHandler.writeInbound(spdyDataFrame); assertDataFrame(sessionHandler.readOutbound(), localStreamId, true); assertNull(sessionHandler.readOutbound()); // Check if session handler sends a GOAWAY frame when closing sessionHandler.writeInbound(closeMessage); assertGoAway(sessionHandler.readOutbound(), localStreamId); assertNull(sessionHandler.readOutbound()); localStreamId += 2; // Check if session handler returns REFUSED_STREAM if it receives // SYN_STREAM frames after sending a GOAWAY frame spdySynStreamFrame.setStreamId(localStreamId); sessionHandler.writeInbound(spdySynStreamFrame); assertRstStream(sessionHandler.readOutbound(), localStreamId, SpdyStreamStatus.REFUSED_STREAM); assertNull(sessionHandler.readOutbound()); // Check if session handler ignores Data frames after sending // a GOAWAY frame spdyDataFrame.setStreamId(localStreamId); sessionHandler.writeInbound(spdyDataFrame); assertNull(sessionHandler.readOutbound()); sessionHandler.finish(); }
@Test public void testPrematureClosureWithChunkedEncoding2() throws Exception { EmbeddedChannel ch = new EmbeddedChannel(new HttpResponseDecoder()); // Write the partial response. ch.writeInbound( Unpooled.copiedBuffer( "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n8\r\n12345678", CharsetUtil.US_ASCII)); // Read the response headers. HttpResponse res = ch.readInbound(); assertThat(res.getProtocolVersion(), sameInstance(HttpVersion.HTTP_1_1)); assertThat(res.getStatus(), is(HttpResponseStatus.OK)); assertThat(res.headers().get(Names.TRANSFER_ENCODING), is("chunked")); // Read the partial content. HttpContent content = ch.readInbound(); assertThat(content.content().toString(CharsetUtil.US_ASCII), is("12345678")); assertThat(content, is(not(instanceOf(LastHttpContent.class)))); content.release(); assertThat(ch.readInbound(), is(nullValue())); // Close the connection. ch.finish(); // The decoder should not generate the last chunk because it's closed prematurely. assertThat(ch.readInbound(), is(nullValue())); }
@Test public void testCompatibleExtensionTogetherSuccess() { // initialize expect(mainHandshakerMock.handshakeExtension(webSocketExtensionDataEqual("main"))) .andReturn(mainExtensionMock) .anyTimes(); expect(mainHandshakerMock.handshakeExtension(webSocketExtensionDataEqual("fallback"))) .andReturn(null) .anyTimes(); replay(mainHandshakerMock); expect(fallbackHandshakerMock.handshakeExtension(webSocketExtensionDataEqual("fallback"))) .andReturn(fallbackExtensionMock) .anyTimes(); expect(fallbackHandshakerMock.handshakeExtension(webSocketExtensionDataEqual("main"))) .andReturn(null) .anyTimes(); replay(fallbackHandshakerMock); expect(mainExtensionMock.rsv()).andReturn(WebSocketExtension.RSV1).anyTimes(); expect(mainExtensionMock.newReponseData()) .andReturn(new WebSocketExtensionData("main", Collections.<String, String>emptyMap())) .once(); expect(mainExtensionMock.newExtensionEncoder()).andReturn(new DummyEncoder()).once(); expect(mainExtensionMock.newExtensionDecoder()).andReturn(new DummyDecoder()).once(); replay(mainExtensionMock); expect(fallbackExtensionMock.rsv()).andReturn(WebSocketExtension.RSV2).anyTimes(); expect(fallbackExtensionMock.newReponseData()) .andReturn(new WebSocketExtensionData("fallback", Collections.<String, String>emptyMap())) .once(); expect(fallbackExtensionMock.newExtensionEncoder()).andReturn(new Dummy2Encoder()).once(); expect(fallbackExtensionMock.newExtensionDecoder()).andReturn(new Dummy2Decoder()).once(); replay(fallbackExtensionMock); // execute EmbeddedChannel ch = new EmbeddedChannel( new WebSocketServerExtensionHandler(mainHandshakerMock, fallbackHandshakerMock)); HttpRequest req = newUpgradeRequest("main, fallback"); ch.writeInbound(req); HttpResponse res = newUpgradeResponse(null); ch.writeOutbound(res); HttpResponse res2 = ch.readOutbound(); List<WebSocketExtensionData> resExts = WebSocketExtensionUtil.extractExtensions( res2.headers().getAndConvert(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS)); // test assertEquals(2, resExts.size()); assertEquals("main", resExts.get(0).name()); assertEquals("fallback", resExts.get(1).name()); assertNotNull(ch.pipeline().get(DummyDecoder.class)); assertNotNull(ch.pipeline().get(DummyEncoder.class)); assertNotNull(ch.pipeline().get(Dummy2Decoder.class)); assertNotNull(ch.pipeline().get(Dummy2Encoder.class)); }
@Test public void testNoneExtensionMatchingSuccess() { // initialize expect(mainHandshakerMock.handshakeExtension(webSocketExtensionDataEqual("unknown"))) .andReturn(null) .anyTimes(); expect(mainHandshakerMock.handshakeExtension(webSocketExtensionDataEqual("unknown2"))) .andReturn(null) .anyTimes(); replay(mainHandshakerMock); expect(fallbackHandshakerMock.handshakeExtension(webSocketExtensionDataEqual("unknown"))) .andReturn(null) .anyTimes(); expect(fallbackHandshakerMock.handshakeExtension(webSocketExtensionDataEqual("unknown2"))) .andReturn(null) .anyTimes(); replay(fallbackHandshakerMock); // execute EmbeddedChannel ch = new EmbeddedChannel( new WebSocketServerExtensionHandler(mainHandshakerMock, fallbackHandshakerMock)); HttpRequest req = newUpgradeRequest("unknown, unknown2"); ch.writeInbound(req); HttpResponse res = newUpgradeResponse(null); ch.writeOutbound(res); HttpResponse res2 = ch.readOutbound(); // test assertFalse(res2.headers().contains(HttpHeaderNames.SEC_WEBSOCKET_EXTENSIONS)); }
@Test public void testLastResponseWithTrailingHeader() { EmbeddedChannel ch = new EmbeddedChannel(new HttpResponseDecoder()); ch.writeInbound( Unpooled.copiedBuffer( "HTTP/1.1 200 OK\r\n" + "Transfer-Encoding: chunked\r\n" + "\r\n" + "0\r\n" + "Set-Cookie: t1=t1v1\r\n" + "Set-Cookie: t2=t2v2; Expires=Wed, 09-Jun-2021 10:18:14 GMT\r\n" + "\r\n", CharsetUtil.US_ASCII)); HttpResponse res = ch.readInbound(); assertThat(res.getProtocolVersion(), sameInstance(HttpVersion.HTTP_1_1)); assertThat(res.getStatus(), is(HttpResponseStatus.OK)); LastHttpContent lastContent = ch.readInbound(); assertThat(lastContent.content().isReadable(), is(false)); HttpHeaders headers = lastContent.trailingHeaders(); assertEquals(1, headers.names().size()); List<String> values = headers.getAll("Set-Cookie"); assertEquals(2, values.size()); assertTrue(values.contains("t1=t1v1")); assertTrue(values.contains("t2=t2v2; Expires=Wed, 09-Jun-2021 10:18:14 GMT")); lastContent.release(); assertThat(ch.finish(), is(false)); assertThat(ch.readInbound(), is(nullValue())); }
@Test public void testValidInitRequest() throws Exception { // Given EmbeddedChannel channel = new EmbeddedChannel(new InitRequestHandler()); InitRequest initRequest = new InitRequest( 42, InitMessage.DEFAULT_VERSION, new HashMap<String, String>() { { put(InitMessage.HOST_PORT_KEY, "0.0.0.0:0"); put(InitMessage.PROCESS_NAME_KEY, "test-process"); } }); channel.writeInbound(initRequest); channel.writeOutbound(channel.readInbound()); // Then InitResponse initResponse = channel.readOutbound(); // Assert assertNotNull(initResponse); assertEquals(initRequest.getId(), initResponse.getId()); assertEquals(initRequest.getVersion(), initResponse.getVersion()); assertEquals(initRequest.getHostPort(), initResponse.getHostPort()); }
@Test public void testRemoveItselfWriteBuffer() { final ByteBuf buf = Unpooled.buffer().writeBytes(new byte[] {'a', 'b', 'c'}); EmbeddedChannel channel = new EmbeddedChannel( new ReplayingDecoder() { private boolean removed; @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { assertFalse(removed); in.readByte(); ctx.pipeline().remove(this); // This should not let it keep call decode buf.writeByte('d'); removed = true; } }); channel.writeInbound(buf.copy()); ByteBuf b = channel.readInbound(); assertEquals(b, Unpooled.wrappedBuffer(new byte[] {'b', 'c'})); b.release(); buf.release(); }
@Test public void testWebSocketResponse() { byte[] data = ("HTTP/1.1 101 WebSocket Protocol Handshake\r\n" + "Upgrade: WebSocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Origin: http://localhost:8080\r\n" + "Sec-WebSocket-Location: ws://localhost/some/path\r\n" + "\r\n" + "1234567812345678") .getBytes(); EmbeddedChannel ch = new EmbeddedChannel(new HttpResponseDecoder()); ch.writeInbound(Unpooled.wrappedBuffer(data)); HttpResponse res = ch.readInbound(); assertThat(res.getProtocolVersion(), sameInstance(HttpVersion.HTTP_1_1)); assertThat(res.getStatus(), is(HttpResponseStatus.SWITCHING_PROTOCOLS)); HttpContent content = ch.readInbound(); assertThat(content.content().readableBytes(), is(16)); content.release(); assertThat(ch.finish(), is(false)); assertThat(ch.readInbound(), is(nullValue())); }
@Test public void testConnect() { StringBuilder builder = new StringBuilder(); try { builder .append("환영합니다. ") .append(InetAddress.getLocalHost().getHostName()) .append("에 접속하셨습니다!\r\n") .append("현재 시간은 ") .append(new Date().toString()) .append(" 입니다.\r\n"); } catch (UnknownHostException e) { fail(); e.printStackTrace(); } EmbeddedChannel embeddedChannel = new EmbeddedChannel(new TelnetServerHandlerV3()); String expected = (String) embeddedChannel.readOutbound(); assertNotNull(expected); assertEquals(builder.toString(), (String) expected); String request = "hello"; expected = "입력하신 명령이 '" + request + "' 입니까?\r\n"; embeddedChannel.writeInbound(request); String response = (String) embeddedChannel.readOutbound(); assertEquals(expected, response); embeddedChannel.finish(); }
@Test public void testIncorrectProtocolVersion() throws Exception { // Given EmbeddedChannel channel = new EmbeddedChannel(new InitRequestHandler()); InitRequest initRequest = new InitRequest( 42, 1, new HashMap<String, String>() { { put(InitMessage.HOST_PORT_KEY, "0.0.0.0:0"); put(InitMessage.PROCESS_NAME_KEY, "test-process"); } }); channel.writeInbound(initRequest); ErrorMessage error = channel.readOutbound(); assertNotNull(error); assertThat(error.getType(), is(ErrorType.FatalProtocolError)); assertThat(error.getMessage(), containsString("version")); this.expectedClosedChannelException.expect(ClosedChannelException.class); channel.writeOutbound(); }
@Test public void testRemoveItselfWithReplayError() { EmbeddedChannel channel = new EmbeddedChannel( new ReplayingDecoder() { private boolean removed; @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { assertFalse(removed); ctx.pipeline().remove(this); in.readBytes(1000); removed = true; } }); ByteBuf buf = Unpooled.wrappedBuffer(new byte[] {'a', 'b', 'c'}); channel.writeInbound(buf.copy()); ByteBuf b = channel.readInbound(); assertEquals("Expect to have still all bytes in the buffer", b, buf); b.release(); buf.release(); }
private void testCompressNone(ZlibWrapper encoderWrapper, ZlibWrapper decoderWrapper) throws Exception { EmbeddedChannel chEncoder = new EmbeddedChannel(createEncoder(encoderWrapper)); // Closing an encoder channel without writing anything should generate both header and footer. assertTrue(chEncoder.finish()); EmbeddedChannel chDecoderZlib = new EmbeddedChannel(createDecoder(decoderWrapper)); for (; ; ) { ByteBuf deflatedData = chEncoder.readOutbound(); if (deflatedData == null) { break; } chDecoderZlib.writeInbound(deflatedData); } // Decoder should not generate anything at all. for (; ; ) { ByteBuf buf = chDecoderZlib.readInbound(); if (buf == null) { break; } buf.release(); fail("should decode nothing"); } assertFalse(chDecoderZlib.finish()); }
@Test public void testClosureWithoutContentLength2() throws Exception { EmbeddedChannel ch = new EmbeddedChannel(new HttpResponseDecoder()); // Write the partial response. ch.writeInbound(Unpooled.copiedBuffer("HTTP/1.1 200 OK\r\n\r\n12345678", CharsetUtil.US_ASCII)); // Read the response headers. HttpResponse res = ch.readInbound(); assertThat(res.getProtocolVersion(), sameInstance(HttpVersion.HTTP_1_1)); assertThat(res.getStatus(), is(HttpResponseStatus.OK)); // Read the partial content. HttpContent content = ch.readInbound(); assertThat(content.content().toString(CharsetUtil.US_ASCII), is("12345678")); assertThat(content, is(not(instanceOf(LastHttpContent.class)))); content.release(); assertThat(ch.readInbound(), is(nullValue())); // Close the connection. assertTrue(ch.finish()); // The decoder should still produce the last content. LastHttpContent lastContent = ch.readInbound(); assertThat(lastContent.content().isReadable(), is(false)); lastContent.release(); // But nothing more. assertThat(ch.readInbound(), is(nullValue())); }
/** * This test makes sure that even when the decoder is confronted with various chunk sizes in the * middle of decoding, it can recover and decode all the time eventually. */ @Test public void shouldHandleNonUniformNetworkBatches() { ByteBuf incoming = Unpooled.copiedBuffer(SET_REQUEST_WITH_CONTENT); while (incoming.isReadable()) { channel.writeInbound(incoming.readBytes(5)); } BinaryMemcacheRequest request = (BinaryMemcacheRequest) channel.readInbound(); assertThat(request, notNullValue()); assertThat(request.getHeader(), notNullValue()); assertThat(request.getKey(), notNullValue()); assertThat(request.getExtras(), nullValue()); request.release(); MemcacheContent content1 = (MemcacheContent) channel.readInbound(); MemcacheContent content2 = (MemcacheContent) channel.readInbound(); assertThat(content1, instanceOf(MemcacheContent.class)); assertThat(content2, instanceOf(LastMemcacheContent.class)); assertThat(content1.content().readableBytes(), is(3)); assertThat(content2.content().readableBytes(), is(5)); content1.release(); content2.release(); }
@Test public void testInboundChainNoChanges() throws Exception { List<Interceptor> interceptors = new ArrayList<>(); MockInterceptor interceptor1 = new MockInterceptor(); MockInterceptor interceptor2 = new MockInterceptor(); interceptors.add(interceptor1); interceptors.add(interceptor2); EmbeddedChannel channel = new EmbeddedChannel( new ChannelDuplexHandler() { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { InterceptorChain chain = new InterceptorChain(ctx, interceptors, (ResourceRequest) msg); chain.fireInbound(); } }); ResourceRequest request = new DefaultResourceRequest.Builder(RequestType.READ, new ResourcePath("/foo/bar")).build(); channel.writeInbound(request); ResourceRequest endRequest = (ResourceRequest) channel.readInbound(); assertThat(endRequest).isNotNull(); assertThat(interceptor1.requests()).hasSize(1); assertThat(interceptor1.requests()).contains(request); assertThat(interceptor2.requests()).hasSize(1); assertThat(interceptor2.requests()).contains(request); }
@Test public void testDummyOutgoingAck() { ch.writeInbound(Unpooled.wrappedBuffer(new byte[] {(byte) 0x81, (byte) 0xFF, 0x00})); UsnIncomingMessage msg = (UsnIncomingMessage) ch.readInbound(); assertEquals(msg.getMessageType(), DUMMY_OUTGOING_ACK); }
@Test public void testDummyIncoming() { ch.writeInbound(Unpooled.wrappedBuffer(new byte[] {0x02, (byte) 0xFF, 0x01, 23})); UsnIncomingMessage msg = (UsnIncomingMessage) ch.readInbound(); assertEquals(msg.getMessageType(), DUMMY_INCOMING); }
@Test public void testRegularDecode() { byte[] b = new byte[2048]; for (int i = 2; i < 2048; i++) { b[i] = 1; } b[0] = -2; b[1] = 15; ch.writeInbound(wrappedBuffer(b, 0, 127)); assertThat(ch.readInbound(), is(nullValue())); ch.writeInbound(wrappedBuffer(b, 127, 600)); assertThat(ch.readInbound(), is(nullValue())); ch.writeInbound(wrappedBuffer(b, 727, b.length - 727)); assertThat( releaseLater((ByteBuf) ch.readInbound()), is(releaseLater(wrappedBuffer(b, 2, b.length - 2)))); }
@Test public void testReplacement() throws Exception { EmbeddedChannel ch = new EmbeddedChannel(new BloatedLineDecoder()); // "AB" should be forwarded to LineDecoder by BloatedLineDecoder. ch.writeInbound(Unpooled.wrappedBuffer(new byte[] {'A', 'B'})); assertNull(ch.readInbound()); // "C\n" should be appended to "AB" so that LineDecoder decodes it correctly. ch.writeInbound(Unpooled.wrappedBuffer(new byte[] {'C', '\n'})); assertEquals( releaseLater(Unpooled.wrappedBuffer(new byte[] {'A', 'B', 'C'})), releaseLater(ch.readInbound())); ch.finish(); assertNull(ch.readInbound()); }
@Test public void testInitHandlerRemovesItself() throws Exception { // Given EmbeddedChannel channel = new EmbeddedChannel(new InitRequestHandler()); assertEquals(3, channel.pipeline().names().size()); InitRequest initRequest = new InitRequest( 42, InitMessage.DEFAULT_VERSION, new HashMap<String, String>() { { put(InitMessage.HOST_PORT_KEY, "0.0.0.0:0"); put(InitMessage.PROCESS_NAME_KEY, "test-process"); } }); channel.writeInbound(initRequest); channel.writeOutbound(channel.readInbound()); // Then InitResponse initResponse = channel.readOutbound(); // Assert assertNotNull(initResponse); assertEquals(initRequest.getId(), initResponse.getId()); assertEquals(initRequest.getVersion(), initResponse.getVersion()); assertEquals(initRequest.getHostPort(), initResponse.getHostPort()); // Assert Pipeline is empty assertEquals(2, channel.pipeline().names().size()); // Make sure Messages are still passed through channel.writeInbound(initRequest); channel.writeOutbound(channel.readInbound()); InitRequest sameInitRequest = channel.readOutbound(); assertEquals(initRequest.getId(), sameInitRequest.getId()); assertEquals(initRequest.getVersion(), sameInitRequest.getVersion()); assertEquals(initRequest.getHostPort(), sameInitRequest.getHostPort()); }
@Test public void testInboundChainShortCircuit() throws Exception { List<Interceptor> interceptors = new ArrayList<>(); ResourceRequest request = new DefaultResourceRequest.Builder(RequestType.READ, new ResourcePath("/foo/bar")).build(); ResourceResponse response = new DefaultResourceErrorResponse(request, ResourceErrorResponse.ErrorType.NOT_AUTHORIZED); MockInterceptor interceptor1 = new MockInterceptor(); MockInterceptor interceptor2 = new MockInterceptor() { @Override public void onInbound(InboundInterceptorContext context) throws Exception { requests.add(context.request()); context.replyWith(response); } }; MockInterceptor interceptor3 = new MockInterceptor(); interceptors.add(interceptor1); interceptors.add(interceptor2); interceptors.add(interceptor3); EmbeddedChannel channel = new EmbeddedChannel( new ChannelDuplexHandler() { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { InterceptorChain chain = new InterceptorChain(ctx, interceptors, (ResourceRequest) msg); chain.fireInbound(); } }); channel.writeInbound(request); ResourceRequest endRequest = (ResourceRequest) channel.readInbound(); Object endResponse = channel.readOutbound(); assertThat(endRequest).isNull(); assertThat(interceptor1.requests()).hasSize(1); assertThat(interceptor1.requests()).contains(request); assertThat(interceptor2.requests()).hasSize(1); assertThat(interceptor2.requests()).contains(request); assertThat(interceptor3.requests()).isEmpty(); assertThat(interceptor3.responses()).isEmpty(); assertThat(interceptor2.responses()).isEmpty(); assertThat(interceptor1.responses()).hasSize(1); assertThat(interceptor1.responses()).contains(response); }