/*
 * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
import com.sun.net.httpserver.HttpsServer;
import jdk.httpclient.test.lib.common.TestServerConfigurator;
import jdk.test.lib.net.SimpleSSLContext;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import jdk.httpclient.test.lib.common.HttpServerAdapters;
import static java.net.http.HttpClient.Version.HTTP_1_1;
import static java.net.http.HttpClient.Version.HTTP_2;

/**
 * @test
 * @bug 8231449
 * @summary This test verifies that the HttpClient works correctly when the server
 *          sends large amount of data. Note that this test will pass even without
 *          the fix for JDK-8231449, which is unfortunate.
 * @library /test/lib /test/jdk/java/net/httpclient/lib
 * @build jdk.httpclient.test.lib.common.HttpServerAdapters
 *        jdk.test.lib.net.SimpleSSLContext DigestEchoServer
 *        jdk.httpclient.test.lib.common.TestServerConfigurator
 * @run main/othervm -Dtest.requiresHost=true
 *                   -Djdk.httpclient.HttpClient.log=headers
 *                   -Djdk.internal.httpclient.debug=true
 *                   LargeResponseTest
 *
 */
public class LargeResponseTest implements HttpServerAdapters {
    static final byte[] DATA;
    static {
        DATA = new byte[64 * 1024];
        int len = 'z' - 'a';
        for (int i=0; i < DATA.length; i++) {
            DATA[i] = (byte) ('a' + (i % len));
        }
    }

    static final SSLContext context;
    static {
        try {
            context = new SimpleSSLContext().get();
            SSLContext.setDefault(context);
        } catch (Exception x) {
            throw new ExceptionInInitializerError(x);
        }
    }

    final AtomicLong requestCounter = new AtomicLong();
    final AtomicLong responseCounter = new AtomicLong();
    HttpTestServer http1Server;
    HttpTestServer http2Server;
    HttpTestServer https1Server;
    HttpTestServer https2Server;
    DigestEchoServer.TunnelingProxy proxy;

    URI http1URI;
    URI https1URI;
    URI http2URI;
    URI https2URI;
    InetSocketAddress proxyAddress;
    ProxySelector proxySelector;
    HttpClient client;
    List<CompletableFuture<?>>  futures = new CopyOnWriteArrayList<>();
    Set<URI> pending = new CopyOnWriteArraySet<>();

    final ExecutorService executor = new ThreadPoolExecutor(12, 60, 10,
            TimeUnit.SECONDS, new LinkedBlockingQueue<>());
    final ExecutorService clientexec = new ThreadPoolExecutor(6, 12, 1,
            TimeUnit.SECONDS, new LinkedBlockingQueue<>());

    public HttpClient newHttpClient(ProxySelector ps) {
        HttpClient.Builder builder = HttpClient
                .newBuilder()
                .sslContext(context)
                .executor(clientexec)
                .proxy(ps);
        return builder.build();
    }

    public void setUp() throws Exception {
        try {
            InetSocketAddress sa = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);

            // HTTP/1.1
            http1Server = HttpTestServer.create(HTTP_1_1, null, executor);
            http1Server.addHandler(new HttpTestLargeHandler(), "/LargeResponseTest/http1/");
            http1Server.start();
            http1URI = new URI("http://" + http1Server.serverAuthority() + "/LargeResponseTest/http1/");


            // HTTPS/1.1
            HttpsServer sserver1 = HttpsServer.create(sa, 100);
            sserver1.setExecutor(executor);
            sserver1.setHttpsConfigurator(new TestServerConfigurator(sa.getAddress(), context));
            https1Server = HttpTestServer.of(sserver1);
            https1Server.addHandler(new HttpTestLargeHandler(), "/LargeResponseTest/https1/");
            https1Server.start();
            https1URI = new URI("https://" + https1Server.serverAuthority() + "/LargeResponseTest/https1/");

            // HTTP/2.0
            http2Server = HttpTestServer.create(HTTP_2);
            http2Server.addHandler(new HttpTestLargeHandler(), "/LargeResponseTest/http2/");
            http2Server.start();
            http2URI = new URI("http://" + http2Server.serverAuthority() + "/LargeResponseTest/http2/");

            // HTTPS/2.0
            https2Server = HttpTestServer.create(HTTP_2, SSLContext.getDefault());
            https2Server.addHandler(new HttpTestLargeHandler(), "/LargeResponseTest/https2/");
            https2Server.start();
            https2URI = new URI("https://" + https2Server.serverAuthority() + "/LargeResponseTest/https2/");

            proxy = DigestEchoServer.createHttpsProxyTunnel(
                    DigestEchoServer.HttpAuthSchemeType.NONE);
            proxyAddress = proxy.getProxyAddress();
            proxySelector = new HttpProxySelector(proxyAddress);
            client = newHttpClient(proxySelector);
            System.out.println("Setup: done");
        } catch (Exception x) {
            tearDown(); throw x;
        } catch (Error e) {
            tearDown(); throw e;
        }
    }

    public static void main(String[] args) throws Exception {
        LargeResponseTest test = new LargeResponseTest();
        test.setUp();
        long start = System.nanoTime();
        try {
            test.run(args);
        } finally {
            try {
                long elapsed = System.nanoTime() - start;
                System.out.println("*** Elapsed: " + Duration.ofNanos(elapsed));
            } finally {
                test.tearDown();
            }
        }
    }

    public void run(String... args) throws Exception {
        List<URI> serverURIs = List.of(http1URI, http2URI, https1URI, https2URI);
        for (int i=0; i<5; i++) {
            for (URI base : serverURIs) {
                if (base.getScheme().equalsIgnoreCase("https")) {
                    URI proxy = i % 1 == 0 ? base.resolve(URI.create("proxy/foo?n="+requestCounter.incrementAndGet()))
                    : base.resolve(URI.create("direct/foo?n="+requestCounter.incrementAndGet()));
                    test(proxy);
                }
            }
            for (URI base : serverURIs) {
                URI direct = base.resolve(URI.create("direct/foo?n="+requestCounter.incrementAndGet()));
                test(direct);
            }
        }
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
    }

    public void test(URI uri) throws Exception {
        System.out.println("Testing with " + uri);
        pending.add(uri);
        HttpRequest request = HttpRequest.newBuilder(uri).build();
        CompletableFuture<HttpResponse<String>> resp =
                client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
                .whenComplete((r, t) -> this.requestCompleted(request, r, t));
        futures.add(resp);
    }

    private void requestCompleted(HttpRequest request, HttpResponse<?> r, Throwable t) {
        responseCounter.incrementAndGet();
        pending.remove(request.uri());
        System.out.println(request + " -> " + (t == null ? r : t)
                + " [still pending: " + (requestCounter.get() - responseCounter.get()) +"]");
        if (pending.size() < 10 && requestCounter.get() > 10) {
            pending.forEach(u -> System.out.println("\tpending: " + u));
        }
    }

    public void tearDown() {
        proxy = stop(proxy, DigestEchoServer.TunnelingProxy::stop);
        http1Server = stop(http1Server, HttpTestServer::stop);
        https1Server = stop(https1Server, HttpTestServer::stop);
        http2Server = stop(http2Server, HttpTestServer::stop);
        https2Server = stop(https2Server, HttpTestServer::stop);
        client = null;
        try {
            executor.awaitTermination(2000, TimeUnit.MILLISECONDS);
        } catch (Throwable x) {
        } finally {
            executor.shutdownNow();
        }
        try {
            clientexec.awaitTermination(2000, TimeUnit.MILLISECONDS);
        } catch (Throwable x) {
        } finally {
            clientexec.shutdownNow();
        }
        System.out.println("Teardown: done");
    }

    private interface Stoppable<T> { public void stop(T service) throws Exception; }

    static <T>  T stop(T service, Stoppable<T> stop) {
        try { if (service != null) stop.stop(service); } catch (Throwable x) { };
        return null;
    }

    static class HttpProxySelector extends ProxySelector {
        private static final List<Proxy> NO_PROXY = List.of(Proxy.NO_PROXY);
        private final List<Proxy> proxyList;
        HttpProxySelector(InetSocketAddress proxyAddress) {
            proxyList = List.of(new Proxy(Proxy.Type.HTTP, proxyAddress));
        }

        @Override
        public List<Proxy> select(URI uri) {
            // our proxy only supports tunneling
            if (uri.getScheme().equalsIgnoreCase("https")) {
                if (uri.getPath().contains("/proxy/")) {
                    return proxyList;
                }
            }
            return NO_PROXY;
        }

        @Override
        public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
            System.err.println("Connection to proxy failed: " + ioe);
            System.err.println("Proxy: " + sa);
            System.err.println("\tURI: " + uri);
            ioe.printStackTrace();
        }
    }

    public static class HttpTestLargeHandler implements HttpTestHandler {
        @Override
        public void handle(HttpTestExchange t) throws IOException {
            try (InputStream is = t.getRequestBody();
                 OutputStream os = t.getResponseBody()) {
                byte[] bytes = is.readAllBytes();
                assert bytes.length == 0;
                URI u = t.getRequestURI();
                long responseID = Long.parseLong(u.getQuery().substring(2));
                System.out.println("Server " + t.getRequestURI() + " sending response " + responseID);
                t.sendResponseHeaders(200, DATA.length * 3);
                for (int i=0; i<3; i++) {
                    os.write(DATA);
                }
                System.out.println("\tresp:" + responseID + ": done");
            }
        }
    }

}
