/*
 * ====================================================================
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 *
 */

package org.apache.hc.core5.testing.classic;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import org.apache.hc.core5.function.Decorator;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.EntityDetails;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpHeaders;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpRequestInterceptor;
import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.HttpVersion;
import org.apache.hc.core5.http.Method;
import org.apache.hc.core5.http.URIScheme;
import org.apache.hc.core5.http.config.Http1Config;
import org.apache.hc.core5.http.io.HttpRequestHandler;
import org.apache.hc.core5.http.io.HttpServerRequestHandler;
import org.apache.hc.core5.http.io.SocketConfig;
import org.apache.hc.core5.http.io.entity.AbstractHttpEntity;
import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.io.support.BasicHttpServerExpectationDecorator;
import org.apache.hc.core5.http.message.BasicClassicHttpRequest;
import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.http.protocol.DefaultHttpProcessor;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.http.protocol.HttpCoreContext;
import org.apache.hc.core5.http.protocol.RequestConnControl;
import org.apache.hc.core5.http.protocol.RequestContent;
import org.apache.hc.core5.http.protocol.RequestExpectContinue;
import org.apache.hc.core5.http.protocol.RequestTargetHost;
import org.apache.hc.core5.http.protocol.RequestUserAgent;
import org.apache.hc.core5.io.CloseMode;
import org.apache.hc.core5.testing.SSLTestContexts;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExternalResource;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class ClassicIntegrationTest {

    @Parameterized.Parameters(name = "{0}")
    public static Collection<Object[]> protocols() {
        return Arrays.asList(new Object[][]{
                { URIScheme.HTTP },
                { URIScheme.HTTPS }
        });
    }

    private final URIScheme scheme;
    private ClassicTestServer server;

    public ClassicIntegrationTest(final URIScheme scheme) {
        this.scheme = scheme;
    }

    @Rule
    public ExternalResource serverResource = new ExternalResource() {

        @Override
        protected void before() throws Throwable {
            server = new ClassicTestServer(
                    scheme == URIScheme.HTTPS ? SSLTestContexts.createServerSSLContext() : null,
                    SocketConfig.custom()
                            .setSoTimeout(5, TimeUnit.SECONDS)
                            .build());
        }

        @Override
        protected void after() {
            if (server != null) {
                try {
                    server.shutdown(CloseMode.IMMEDIATE);
                    server = null;
                } catch (final Exception ignore) {
                }
            }
        }

    };

    private ClassicTestClient client;

    @Rule
    public ExternalResource clientResource = new ExternalResource() {

        @Override
        protected void before() throws Throwable {
            client = new ClassicTestClient(
                    scheme == URIScheme.HTTPS  ? SSLTestContexts.createClientSSLContext() : null,
                    SocketConfig.custom()
                            .setSoTimeout(5, TimeUnit.SECONDS)
                            .build());
        }

        @Override
        protected void after() {
            if (client != null) {
                try {
                    client.shutdown(CloseMode.IMMEDIATE);
                    client = null;
                } catch (final Exception ignore) {
                }
            }
        }

    };

    /**
     * This test case executes a series of simple GET requests
     */
    @Test
    public void testSimpleBasicHttpRequests() throws Exception {

        final int reqNo = 20;

        final Random rnd = new Random();

        // Prepare some random data
        final List<byte[]> testData = new ArrayList<>(reqNo);
        for (int i = 0; i < reqNo; i++) {
            final int size = rnd.nextInt(5000);
            final byte[] data = new byte[size];
            rnd.nextBytes(data);
            testData.add(data);
        }

        // Initialize the server-side request handler
        this.server.registerHandler("*", new HttpRequestHandler() {

            @Override
            public void handle(
                    final ClassicHttpRequest request,
                    final ClassicHttpResponse response,
                    final HttpContext context) throws HttpException, IOException {

                String s = request.getPath();
                if (s.startsWith("/?")) {
                    s = s.substring(2);
                }
                final int index = Integer.parseInt(s);
                final byte[] data = testData.get(index);
                final ByteArrayEntity entity = new ByteArrayEntity(data, null);
                response.setEntity(entity);
            }

        });

        this.server.start();
        this.client.start();

        final HttpCoreContext context = HttpCoreContext.create();
        final HttpHost host = new HttpHost(scheme.id, "localhost", this.server.getPort());

        for (int r = 0; r < reqNo; r++) {
            final BasicClassicHttpRequest get = new BasicClassicHttpRequest(Method.GET, "/?" + r);
            try (final ClassicHttpResponse response = this.client.execute(host, get, context)) {
                final byte[] received = EntityUtils.toByteArray(response.getEntity());
                final byte[] expected = testData.get(r);

                Assert.assertEquals(expected.length, received.length);
                for (int i = 0; i < expected.length; i++) {
                    Assert.assertEquals(expected[i], received[i]);
                }
            }
        }
    }

    /**
     * This test case executes a series of simple POST requests with content length
     * delimited content.
     */
    @Test
    public void testSimpleHttpPostsWithContentLength() throws Exception {

        final int reqNo = 20;

        final Random rnd = new Random();

        // Prepare some random data
        final List<byte[]> testData = new ArrayList<>(reqNo);
        for (int i = 0; i < reqNo; i++) {
            final int size = rnd.nextInt(5000);
            final byte[] data = new byte[size];
            rnd.nextBytes(data);
            testData.add(data);
        }

        // Initialize the server-side request handler
        this.server.registerHandler("*", new HttpRequestHandler() {

            @Override
            public void handle(
                    final ClassicHttpRequest request,
                    final ClassicHttpResponse response,
                    final HttpContext context) throws HttpException, IOException {

                final HttpEntity entity = request.getEntity();
                if (entity != null) {
                    final byte[] data = EntityUtils.toByteArray(entity);
                    response.setEntity(new ByteArrayEntity(data, null));
                }
            }

        });

        this.server.start();
        this.client.start();

        final HttpCoreContext context = HttpCoreContext.create();
        final HttpHost host = new HttpHost(scheme.id, "localhost", this.server.getPort());

        for (int r = 0; r < reqNo; r++) {
            final BasicClassicHttpRequest post = new BasicClassicHttpRequest(Method.POST, "/");
            final byte[] data = testData.get(r);
            post.setEntity(new ByteArrayEntity(data, null));

            try (final ClassicHttpResponse response = this.client.execute(host, post, context)) {
                final byte[] received = EntityUtils.toByteArray(response.getEntity());
                final byte[] expected = testData.get(r);

                Assert.assertEquals(expected.length, received.length);
                for (int i = 0; i < expected.length; i++) {
                    Assert.assertEquals(expected[i], received[i]);
                }
            }
        }
    }

    /**
     * This test case executes a series of simple POST requests with chunk
     * coded content content.
     */
    @Test
    public void testSimpleHttpPostsChunked() throws Exception {

        final int reqNo = 20;

        final Random rnd = new Random();

        // Prepare some random data
        final List<byte[]> testData = new ArrayList<>(reqNo);
        for (int i = 0; i < reqNo; i++) {
            final int size = rnd.nextInt(20000);
            final byte[] data = new byte[size];
            rnd.nextBytes(data);
            testData.add(data);
        }

        // Initialize the server-side request handler
        this.server.registerHandler("*", new HttpRequestHandler() {

            @Override
            public void handle(
                    final ClassicHttpRequest request,
                    final ClassicHttpResponse response,
                    final HttpContext context) throws HttpException, IOException {

                final HttpEntity entity = request.getEntity();
                if (entity != null) {
                    final byte[] data = EntityUtils.toByteArray(entity);
                    response.setEntity(new ByteArrayEntity(data, null, true));
                }
            }

        });

        this.server.start();
        this.client.start();

        final HttpCoreContext context = HttpCoreContext.create();
        final HttpHost host = new HttpHost(scheme.id, "localhost", this.server.getPort());

        for (int r = 0; r < reqNo; r++) {
            final BasicClassicHttpRequest post = new BasicClassicHttpRequest(Method.POST, "/");
            final byte[] data = testData.get(r);
            post.setEntity(new ByteArrayEntity(data, null, true));

            try (final ClassicHttpResponse response = this.client.execute(host, post, context)) {
                final byte[] received = EntityUtils.toByteArray(response.getEntity());
                final byte[] expected = testData.get(r);

                Assert.assertEquals(expected.length, received.length);
                for (int i = 0; i < expected.length; i++) {
                    Assert.assertEquals(expected[i], received[i]);
                }
            }
        }
    }

    /**
     * This test case executes a series of simple HTTP/1.0 POST requests.
     */
    @Test
    public void testSimpleHttpPostsHTTP10() throws Exception {

        final int reqNo = 20;

        final Random rnd = new Random();

        // Prepare some random data
        final List<byte[]> testData = new ArrayList<>(reqNo);
        for (int i = 0; i < reqNo; i++) {
            final int size = rnd.nextInt(5000);
            final byte[] data = new byte[size];
            rnd.nextBytes(data);
            testData.add(data);
        }

        // Initialize the server-side request handler
        this.server.registerHandler("*", new HttpRequestHandler() {

            @Override
            public void handle(
                    final ClassicHttpRequest request,
                    final ClassicHttpResponse response,
                    final HttpContext context) throws HttpException, IOException {

                final HttpEntity entity = request.getEntity();
                if (entity != null) {
                    final byte[] data = EntityUtils.toByteArray(entity);
                    response.setEntity(new ByteArrayEntity(data, null));
                }
                if (HttpVersion.HTTP_1_0.equals(request.getVersion())) {
                    response.addHeader("Version", "1.0");
                }
            }

        });

        this.server.start();
        this.client.start();

        final HttpCoreContext context = HttpCoreContext.create();
        final HttpHost host = new HttpHost(scheme.id, "localhost", this.server.getPort());

        for (int r = 0; r < reqNo; r++) {
            // Set protocol level to HTTP/1.0
            final BasicClassicHttpRequest post = new BasicClassicHttpRequest(Method.POST, "/");
            post.setVersion(HttpVersion.HTTP_1_0);
            final byte[] data = testData.get(r);
            post.setEntity(new ByteArrayEntity(data, null));

            try (final ClassicHttpResponse response = this.client.execute(host, post, context)) {
                Assert.assertEquals(HttpVersion.HTTP_1_1, response.getVersion());
                final Header h1 = response.getFirstHeader("Version");
                Assert.assertNotNull(h1);
                Assert.assertEquals("1.0", h1.getValue());
                final byte[] received = EntityUtils.toByteArray(response.getEntity());
                final byte[] expected = testData.get(r);

                Assert.assertEquals(expected.length, received.length);
                for (int i = 0; i < expected.length; i++) {
                    Assert.assertEquals(expected[i], received[i]);
                }
            }
        }
    }

    /**
     * This test case executes a series of simple POST requests using
     * the 'expect: continue' handshake.
     */
    @Test
    public void testHttpPostsWithExpectContinue() throws Exception {

        final int reqNo = 20;

        final Random rnd = new Random();

        // Prepare some random data
        final List<byte[]> testData = new ArrayList<>(reqNo);
        for (int i = 0; i < reqNo; i++) {
            final int size = rnd.nextInt(5000);
            final byte[] data = new byte[size];
            rnd.nextBytes(data);
            testData.add(data);
        }

        // Initialize the server-side request handler
        this.server.registerHandler("*", new HttpRequestHandler() {

            @Override
            public void handle(
                    final ClassicHttpRequest request,
                    final ClassicHttpResponse response,
                    final HttpContext context) throws HttpException, IOException {

                final HttpEntity entity = request.getEntity();
                if (entity != null) {
                    final byte[] data = EntityUtils.toByteArray(entity);
                    response.setEntity(new ByteArrayEntity(data, null, true));
                }
            }

        });

        this.server.start();
        this.client.start();

        final HttpCoreContext context = HttpCoreContext.create();
        final HttpHost host = new HttpHost(scheme.id, "localhost", this.server.getPort());

        for (int r = 0; r < reqNo; r++) {
            final BasicClassicHttpRequest post = new BasicClassicHttpRequest(Method.POST, "/");
            final byte[] data = testData.get(r);
            post.setEntity(new ByteArrayEntity(data, null, true));

            try (final ClassicHttpResponse response = this.client.execute(host, post, context)) {
                final byte[] received = EntityUtils.toByteArray(response.getEntity());
                final byte[] expected = testData.get(r);

                Assert.assertEquals(expected.length, received.length);
                for (int i = 0; i < expected.length; i++) {
                    Assert.assertEquals(expected[i], received[i]);
                }
            }
        }
    }

    /**
     * This test case executes a series of simple POST requests that do not
     * meet the target server expectations.
     */
    @Test
    public void testHttpPostsWithExpectationVerification() throws Exception {

        final int reqNo = 20;

        // Initialize the server-side request handler
        this.server.registerHandler("*", new HttpRequestHandler() {

            @Override
            public void handle(
                    final ClassicHttpRequest request,
                    final ClassicHttpResponse response,
                    final HttpContext context) throws HttpException, IOException {

                response.setEntity(new StringEntity("No content"));
            }

        });

        this.server.start(null, null, new Decorator<HttpServerRequestHandler>() {

            @Override
            public HttpServerRequestHandler decorate(final HttpServerRequestHandler handler) {
                return new BasicHttpServerExpectationDecorator(handler) {

                    @Override
                    protected ClassicHttpResponse verify(final ClassicHttpRequest request, final HttpContext context) {
                        final Header someheader = request.getFirstHeader("Secret");
                        if (someheader != null) {
                            final int secretNumber;
                            try {
                                secretNumber = Integer.parseInt(someheader.getValue());
                            } catch (final NumberFormatException ex) {
                                final ClassicHttpResponse response = new BasicClassicHttpResponse(HttpStatus.SC_BAD_REQUEST);
                                response.setEntity(new StringEntity(ex.toString()));
                                return response;
                            }
                            if (secretNumber >= 2) {
                                final ClassicHttpResponse response = new BasicClassicHttpResponse(HttpStatus.SC_EXPECTATION_FAILED);
                                response.setEntity(new StringEntity("Wrong secret number", ContentType.TEXT_PLAIN));
                                return response;
                            }
                        }
                        return null;
                    }

                };
            }

        });
        this.client.start();

        final HttpCoreContext context = HttpCoreContext.create();
        final HttpHost host = new HttpHost(scheme.id, "localhost", this.server.getPort());

        for (int r = 0; r < reqNo; r++) {
            final BasicClassicHttpRequest post = new BasicClassicHttpRequest(Method.POST, "/");
            post.addHeader("Secret", Integer.toString(r));

            final byte[] b = new byte[2048];
            for (int i = 0; i < b.length; i++) {
                b[i] = (byte) ('a' + r);
            }
            post.setEntity(new ByteArrayEntity(b, ContentType.TEXT_PLAIN));

            try (final ClassicHttpResponse response = this.client.execute(host, post, context)) {
                final HttpEntity responseEntity = response.getEntity();
                Assert.assertNotNull(responseEntity);
                EntityUtils.consume(responseEntity);

                if (r >= 2) {
                    Assert.assertEquals(HttpStatus.SC_EXPECTATION_FAILED, response.getCode());
                } else {
                    Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
                }
            }
        }
    }

    static class RepeatingEntity extends AbstractHttpEntity {

        private final byte[] raw;
        private final int n;

        public RepeatingEntity(final String content, final Charset charset, final int n, final boolean chunked) {
            super(ContentType.TEXT_PLAIN.withCharset(charset), null, chunked);
            final Charset cs = charset != null ? charset : Charset.forName("US-ASCII");
            this.raw = content.getBytes(cs);
            this.n = n;
        }

        @Override
        public InputStream getContent() throws IOException, IllegalStateException {
            throw new IllegalStateException("This method is not implemented");
        }

        @Override
        public long getContentLength() {
            return (this.raw.length + 2) * this.n;
        }

        @Override
        public boolean isRepeatable() {
            return true;
        }

        @Override
        public boolean isStreaming() {
            return false;
        }

        @Override
        public void writeTo(final OutputStream outStream) throws IOException {
            for (int i = 0; i < this.n; i++) {
                outStream.write(this.raw);
                outStream.write('\r');
                outStream.write('\n');
            }
            outStream.flush();
        }

        @Override
        public void close() throws IOException {
        }

    }

    @Test
    public void testHttpContent() throws Exception {

        final String[] patterns = {

            "0123456789ABCDEF",
            "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
            "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
            "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
            "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
            "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
            "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
            "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
            "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
            "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
            "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
            "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
            "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
            "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
            "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that-" +
            "yadayada-blahblah-this-and-that-yadayada-blahblah-this-and-that"
        };

        // Initialize the server-side request handler
        this.server.registerHandler("*", new HttpRequestHandler() {

            @Override
            public void handle(
                    final ClassicHttpRequest request,
                    final ClassicHttpResponse response,
                    final HttpContext context) throws HttpException, IOException {

                int n = 1;
                String s = request.getPath();
                if (s.startsWith("/?n=")) {
                    s = s.substring(4);
                    try {
                        n = Integer.parseInt(s);
                        if (n <= 0) {
                            throw new HttpException("Invalid request: " +
                                    "number of repetitions cannot be negative or zero");
                        }
                    } catch (final NumberFormatException ex) {
                        throw new HttpException("Invalid request: " +
                                "number of repetitions is invalid");
                    }
                }

                final HttpEntity entity = request.getEntity();
                if (entity != null) {
                    final String line = EntityUtils.toString(entity);
                    final ContentType contentType = ContentType.parse(entity.getContentType());
                    Charset charset = contentType.getCharset();
                    if (charset == null) {
                        charset = StandardCharsets.ISO_8859_1;
                    }
                    response.setEntity(new RepeatingEntity(line, charset, n, n % 2 == 0));
                }
            }

        });

        this.server.start();
        this.client.start();

        final HttpCoreContext context = HttpCoreContext.create();
        final HttpHost host = new HttpHost(scheme.id, "localhost", this.server.getPort());

        for (final String pattern : patterns) {
            for (int n = 1000; n < 1020; n++) {
                final BasicClassicHttpRequest post = new BasicClassicHttpRequest(
                        Method.POST.name(), "/?n=" + n);
                post.setEntity(new StringEntity(pattern, ContentType.TEXT_PLAIN, n % 2 == 0));

                try (final ClassicHttpResponse response = this.client.execute(host, post, context)) {
                    final HttpEntity entity = response.getEntity();
                    Assert.assertNotNull(entity);
                    final InputStream inStream = entity.getContent();
                    final ContentType contentType = ContentType.parse(entity.getContentType());
                    Charset charset = contentType.getCharset();
                    if (charset == null) {
                        charset = StandardCharsets.ISO_8859_1;
                    }
                    Assert.assertNotNull(inStream);
                    final BufferedReader reader = new BufferedReader(new InputStreamReader(inStream, charset));

                    String line;
                    int count = 0;
                    while ((line = reader.readLine()) != null) {
                        Assert.assertEquals(pattern, line);
                        count++;
                    }
                    Assert.assertEquals(n, count);
                }
            }
        }
    }

    @Test
    public void testHttpPostNoEntity() throws Exception {
        this.server.registerHandler("*", new HttpRequestHandler() {

            @Override
            public void handle(
                    final ClassicHttpRequest request,
                    final ClassicHttpResponse response,
                    final HttpContext context) throws HttpException, IOException {

                final HttpEntity entity = request.getEntity();
                if (entity != null) {
                    final byte[] data = EntityUtils.toByteArray(entity);
                    response.setEntity(new ByteArrayEntity(data, null));
                }
            }

        });

        this.server.start();
        this.client.start();

        final HttpCoreContext context = HttpCoreContext.create();
        final HttpHost host = new HttpHost(scheme.id, "localhost", this.server.getPort());

        final BasicClassicHttpRequest post = new BasicClassicHttpRequest(Method.POST, "/");
        post.setEntity(null);

        try (final ClassicHttpResponse response = this.client.execute(host, post, context)) {
            Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
            final byte[] received = EntityUtils.toByteArray(response.getEntity());
            Assert.assertEquals(0, received.length);
        }
    }

    @Test
    public void testHttpPostNoContentLength() throws Exception {
        this.server.registerHandler("*", new HttpRequestHandler() {

            @Override
            public void handle(
                    final ClassicHttpRequest request,
                    final ClassicHttpResponse response,
                    final HttpContext context) throws HttpException, IOException {

                final HttpEntity entity = request.getEntity();
                if (entity != null) {
                    final byte[] data = EntityUtils.toByteArray(entity);
                    response.setEntity(new ByteArrayEntity(data, null));
                }
            }

        });

        this.server.start();
        this.client.start(new DefaultHttpProcessor(
                new RequestTargetHost(),
                new RequestConnControl(),
                new RequestUserAgent(),
                new RequestExpectContinue()));

        final HttpCoreContext context = HttpCoreContext.create();
        final HttpHost host = new HttpHost(scheme.id, "localhost", this.server.getPort());

        final BasicClassicHttpRequest post = new BasicClassicHttpRequest(Method.POST, "/");
        post.setEntity(null);

        try (final ClassicHttpResponse response = this.client.execute(host, post, context)) {
            Assert.assertEquals(HttpStatus.SC_OK, response.getCode());
            final byte[] received = EntityUtils.toByteArray(response.getEntity());
            Assert.assertEquals(0, received.length);
        }
    }

    @Test
    public void testHttpPostIdentity() throws Exception {
        this.server.registerHandler("*", new HttpRequestHandler() {

            @Override
            public void handle(
                    final ClassicHttpRequest request,
                    final ClassicHttpResponse response,
                    final HttpContext context) throws HttpException, IOException {

                final HttpEntity entity = request.getEntity();
                if (entity != null) {
                    final byte[] data = EntityUtils.toByteArray(entity);
                    response.setEntity(new ByteArrayEntity(data, null));
                }
            }

        });

        this.server.start();
        this.client.start(new DefaultHttpProcessor(
                new HttpRequestInterceptor() {

                    @Override
                    public void process(
                            final HttpRequest request,
                            final EntityDetails entity,
                            final HttpContext context) throws HttpException, IOException {
                        request.addHeader(HttpHeaders.TRANSFER_ENCODING, "identity");
                    }

                },
                new RequestTargetHost(),
                new RequestConnControl(),
                new RequestUserAgent(),
                new RequestExpectContinue()));

        final HttpCoreContext context = HttpCoreContext.create();
        final HttpHost host = new HttpHost(scheme.id, "localhost", this.server.getPort());

        final BasicClassicHttpRequest post = new BasicClassicHttpRequest(Method.POST, "/");
        post.setEntity(null);

        try (final ClassicHttpResponse response = this.client.execute(host, post, context)) {
            Assert.assertEquals(HttpStatus.SC_NOT_IMPLEMENTED, response.getCode());
        }
    }

    @Test
    public void testNoContentResponse() throws Exception {

        final int reqNo = 20;

        // Initialize the server-side request handler
        this.server.registerHandler("*", new HttpRequestHandler() {

            @Override
            public void handle(
                    final ClassicHttpRequest request,
                    final ClassicHttpResponse response,
                    final HttpContext context) throws HttpException, IOException {
                response.setCode(HttpStatus.SC_NO_CONTENT);
            }

        });

        this.server.start();
        this.client.start();

        final HttpCoreContext context = HttpCoreContext.create();
        final HttpHost host = new HttpHost(scheme.id, "localhost", this.server.getPort());

        for (int r = 0; r < reqNo; r++) {
            final BasicClassicHttpRequest get = new BasicClassicHttpRequest(Method.GET, "/?" + r);
            try (final ClassicHttpResponse response = this.client.execute(host, get, context)) {
                Assert.assertNull(response.getEntity());
            }
        }
    }

    @Test
    public void testAbsentHostHeader() throws Exception {

        // Initialize the server-side request handler
        this.server.registerHandler("*", new HttpRequestHandler() {

            @Override
            public void handle(
                    final ClassicHttpRequest request,
                    final ClassicHttpResponse response,
                    final HttpContext context) throws HttpException, IOException {
                response.setEntity(new StringEntity("All is well", StandardCharsets.US_ASCII));
            }

        });

        this.server.start();
        this.client.start(new DefaultHttpProcessor(new RequestContent(), new RequestConnControl()));

        final HttpCoreContext context = HttpCoreContext.create();
        final HttpHost host = new HttpHost(scheme.id, "localhost", this.server.getPort());

        final BasicClassicHttpRequest get1 = new BasicClassicHttpRequest(Method.GET, "/");
        get1.setVersion(HttpVersion.HTTP_1_0);
        try (final ClassicHttpResponse response1 = this.client.execute(host, get1, context)) {
            Assert.assertEquals(200, response1.getCode());
            EntityUtils.consume(response1.getEntity());
        }

        final BasicClassicHttpRequest get2 = new BasicClassicHttpRequest(Method.GET, "/");
        try (final ClassicHttpResponse response2 = this.client.execute(host, get2, context)) {
            Assert.assertEquals(400, response2.getCode());
            EntityUtils.consume(response2.getEntity());
        }
    }

    @Test
    public void testHeaderTooLarge() throws Exception {
        this.server.registerHandler("*", new HttpRequestHandler() {

            @Override
            public void handle(
                    final ClassicHttpRequest request,
                    final ClassicHttpResponse response,
                    final HttpContext context) throws HttpException, IOException {
                response.setEntity(new StringEntity("All is well", StandardCharsets.US_ASCII));
            }

        });

        this.server.start(
                Http1Config.custom()
                        .setMaxLineLength(100)
                        .build(),
                null,
                null);
        this.client.start();

        final HttpCoreContext context = HttpCoreContext.create();
        final HttpHost host = new HttpHost(scheme.id, "localhost", this.server.getPort());

        final BasicClassicHttpRequest get1 = new BasicClassicHttpRequest(Method.GET, "/");
        get1.setHeader("big-f-header", "1234567890123456789012345678901234567890123456789012345678901234567890" +
                "1234567890123456789012345678901234567890");
        try (final ClassicHttpResponse response1 = this.client.execute(host, get1, context)) {
            Assert.assertEquals(431, response1.getCode());
            EntityUtils.consume(response1.getEntity());
        }
    }

    @Test
    public void testHeaderTooLargePost() throws Exception {
        this.server.registerHandler("*", new HttpRequestHandler() {

            @Override
            public void handle(
                    final ClassicHttpRequest request,
                    final ClassicHttpResponse response,
                    final HttpContext context) throws HttpException, IOException {
                response.setEntity(new StringEntity("All is well", StandardCharsets.US_ASCII));
            }

        });

        this.server.start(
                Http1Config.custom()
                        .setMaxLineLength(100)
                        .build(),
                null,
                null);
        this.client.start(
                new DefaultHttpProcessor(new RequestContent(), new RequestTargetHost(), new RequestConnControl()));

        final HttpCoreContext context = HttpCoreContext.create();
        final HttpHost host = new HttpHost(scheme.id, "localhost", this.server.getPort());

        final ClassicHttpRequest post1 = new BasicClassicHttpRequest(Method.POST, "/");
        post1.setHeader("big-f-header", "1234567890123456789012345678901234567890123456789012345678901234567890" +
                "1234567890123456789012345678901234567890");
        final byte[] b = new byte[2048];
        for (int i = 0; i < b.length; i++) {
            b[i] = (byte) ('a' + i % 10);
        }
        post1.setEntity(new ByteArrayEntity(b, ContentType.TEXT_PLAIN));

        try (final ClassicHttpResponse response1 = this.client.execute(host, post1, context)) {
            Assert.assertEquals(431, response1.getCode());
            EntityUtils.consume(response1.getEntity());
        }
    }

}
