@Test
  public void testLargeFileRegionChunked() throws Exception {
    EmbeddedChannel channel = new EmbeddedChannel(new HttpResponseEncoder());
    HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
    response.headers().set(HttpHeaders.Names.TRANSFER_ENCODING, HttpHeaders.Values.CHUNKED);
    assertTrue(channel.writeOutbound(response));

    ByteBuf buffer = channel.readOutbound();

    assertEquals(
        "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n",
        buffer.toString(CharsetUtil.US_ASCII));
    buffer.release();
    assertTrue(channel.writeOutbound(FILE_REGION));
    buffer = channel.readOutbound();
    assertEquals("80000000\r\n", buffer.toString(CharsetUtil.US_ASCII));
    buffer.release();

    FileRegion region = channel.readOutbound();
    assertSame(FILE_REGION, region);
    region.release();
    buffer = channel.readOutbound();
    assertEquals("\r\n", buffer.toString(CharsetUtil.US_ASCII));
    buffer.release();

    assertTrue(channel.writeOutbound(LastHttpContent.EMPTY_LAST_CONTENT));
    buffer = channel.readOutbound();
    assertEquals("0\r\n\r\n", buffer.toString(CharsetUtil.US_ASCII));
    buffer.release();

    assertFalse(channel.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 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 testPrematureClosureWithChunkedEncoding1() throws Exception {
    EmbeddedChannel ch = new EmbeddedChannel(new HttpResponseDecoder());
    ch.writeInbound(
        Unpooled.copiedBuffer(
            "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n", 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"));
    assertThat(ch.readInbound(), is(nullValue()));

    // Close the connection without sending anything.
    ch.finish();
    // The decoder should not generate the last chunk because it's closed prematurely.
    assertThat(ch.readInbound(), is(nullValue()));
  }