/*
 * Copyright (c) 2022, 2025, 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 jdk.test.lib.net.IPSupport;
import jdk.test.lib.net.SimpleSSLContext;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import javax.net.ssl.SSLContext;
import java.io.Closeable;
import java.net.InetAddress;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import java.util.function.Supplier;

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
 * @summary Tests HttpClient usage when configured with a local address to bind
 *          to, when sending requests
 * @bug 8209137 8316031
 * @library /test/lib /test/jdk/java/net/httpclient/lib
 *
 * @build jdk.test.lib.net.SimpleSSLContext jdk.test.lib.net.IPSupport
 *        jdk.httpclient.test.lib.common.HttpServerAdapters
 *
 * @run testng/othervm
 *      -Djdk.httpclient.HttpClient.log=frames,ssl,requests,responses,errors
 *      -Djdk.internal.httpclient.debug=true
 *      -Dsun.net.httpserver.idleInterval=50000
 *      HttpClientLocalAddrTest
 *
 */
public class HttpClientLocalAddrTest implements HttpServerAdapters {

    private static SSLContext sslContext;
    private static HttpServerAdapters.HttpTestServer http1_1_Server;
    private static URI httpURI;
    private static HttpServerAdapters.HttpTestServer https_1_1_Server;
    private static URI httpsURI;
    private static HttpServerAdapters.HttpTestServer http2_Server;
    private static URI http2URI;
    private static HttpServerAdapters.HttpTestServer https2_Server;
    private static URI https2URI;
    private static final AtomicInteger IDS = new AtomicInteger();

    // start various HTTP/HTTPS servers that will be invoked against in the tests
    @BeforeClass
    public static void beforeClass() throws Exception {
        sslContext = new SimpleSSLContext().get();
        Assert.assertNotNull(sslContext, "Unexpected null sslContext");

        HttpServerAdapters.HttpTestHandler handler = (exchange) -> {
            // the handler receives a request and sends back a 200 response with the
            // response body containing the raw IP address (in byte[] form) of the client from whom
            // the request was received
            var clientAddr = exchange.getRemoteAddress();
            System.out.println("Received a request from client address " + clientAddr);
            var responseContent = clientAddr.getAddress().getAddress();
            exchange.sendResponseHeaders(200, responseContent.length);
            try (var os = exchange.getResponseBody()) {
                // write out the client address as a response
                os.write(responseContent);
            }
            exchange.close();
        };

        // HTTP/1.1 - create servers with http and https
        http1_1_Server = HttpServerAdapters.HttpTestServer.create(HTTP_1_1);
        http1_1_Server.addHandler(handler, "/");
        http1_1_Server.start();
        System.out.println("Started HTTP v1.1 server at " + http1_1_Server.serverAuthority());
        httpURI = new URI("http://" + http1_1_Server.serverAuthority() + "/");

        https_1_1_Server = HttpServerAdapters.HttpTestServer.create(HTTP_1_1, sslContext);
        https_1_1_Server.addHandler(handler, "/");
        https_1_1_Server.start();
        System.out.println("Started HTTPS v1.1 server at " + https_1_1_Server.serverAuthority());
        httpsURI = new URI("https://" + https_1_1_Server.serverAuthority() + "/");

        // HTTP/2 - create servers with http and https
        http2_Server = HttpServerAdapters.HttpTestServer.create(HTTP_2);
        http2_Server.addHandler(handler, "/");
        http2_Server.start();
        System.out.println("Started HTTP v2 server at " + http2_Server.serverAuthority());
        http2URI = new URI("http://" + http2_Server.serverAuthority() + "/");

        https2_Server = HttpServerAdapters.HttpTestServer.create(HTTP_2, sslContext);
        https2_Server.addHandler(handler, "/");
        https2_Server.start();
        System.out.println("Started HTTPS v2 server at " + https2_Server.serverAuthority());
        https2URI = new URI("https://" + https2_Server.serverAuthority() + "/");
    }

    // stop each of the started servers
    @AfterClass
    public static void afterClass() throws Exception {
        // stop each of the server and accumulate any exception
        // that might happen during stop and finally throw
        // the accumulated exception(s)
        var e = safeStop(http1_1_Server, null);
        e = safeStop(https_1_1_Server, e);
        e = safeStop(http2_Server, e);
        e = safeStop(https2_Server, e);
        // throw any exception that happened during stop
        if (e != null) {
            throw e;
        }
    }

    /**
     * Stops the server and returns (instead of throwing) any exception that might
     * have occurred during stop. If {@code prevException} is not null then any
     * exception during stop of the {@code server} will be added as a suppressed
     * exception to the {@code prevException} and the {@code prevException} will be
     * returned.
     */
    private static Exception safeStop(HttpServerAdapters.HttpTestServer server, Exception prevException) {
        if (server == null) {
            return null;
        }
        var serverAuthority = server.serverAuthority();
        try {
            server.stop();
        } catch (Exception e) {
            System.err.println("Failed to stop server " + serverAuthority);
            if (prevException == null) {
                return e;
            }
            prevException.addSuppressed(e);
            return prevException;
        }
        return prevException;
    }

    @DataProvider(name = "params")
    private Object[][] paramsProvider() throws Exception {
        final List<Object[]> testMethodParams = new ArrayList<>();
        final URI[] requestURIs = new URI[]{httpURI, httpsURI, http2URI, https2URI};
        final Predicate<URI> requiresSSLContext = (uri) -> uri.getScheme().equals("https");
        for (var requestURI : requestURIs) {
            final var configureClientSSL = requiresSSLContext.test(requestURI);
            // no localAddr set
            testMethodParams.add(new Object[]{
                    newBuilder(configureClientSSL).provider(),
                    requestURI,
                    null
            });
            // null localAddr set
            testMethodParams.add(new Object[]{
                    newBuilder(configureClientSSL).localAddress(null).provider(),
                    requestURI,
                    null
            });
            // localAddr set to loopback address
            final var loopbackAddr = InetAddress.getLoopbackAddress();
            testMethodParams.add(new Object[]{
                    newBuilder(configureClientSSL)
                            .localAddress(loopbackAddr)
                            .provider(),
                    requestURI,
                    loopbackAddr
            });
            // anyAddress
            if (IPSupport.hasIPv6()) {
                // ipv6 wildcard
                final var localAddr = InetAddress.getByName("::");
                testMethodParams.add(new Object[]{
                        newBuilder(configureClientSSL)
                                .localAddress(localAddr)
                                .provider(),
                        requestURI,
                        localAddr
                });
            }
            if (IPSupport.hasIPv4()) {
                // ipv4 wildcard
                final var localAddr = InetAddress.getByName("0.0.0.0");
                testMethodParams.add(new Object[]{
                        newBuilder(configureClientSSL)
                                .localAddress(localAddr)
                                .provider(),
                        requestURI,
                        localAddr
                });
            }
        }
        return testMethodParams.stream().toArray(Object[][]::new);
    }

    // An object that holds a client and that can be closed
    // Used when closing the client might require closing additional
    // resources, such as an executor
    sealed interface ClientCloseable extends Closeable {

        HttpClient client();

        @Override
        void close();

        // a reusable client that does nothing when close() is called,
        // so that the underlying client can be reused
        record ReusableClient(HttpClient client) implements ClientCloseable {
            // do not close the client so that it can be reused
            @Override
            public void close() { }
        }

        // a client configured with an executor, that closes both the client
        // and the executor when close() is called
        record ClientWithExecutor(HttpClient client, ExecutorService service)
                implements ClientCloseable {
            // close both the client and executor
            @Override
            public void close() {
                client.close();
                service.close();
            }
        }

        static ReusableClient reusable(HttpClient client) {
            return new ReusableClient(client);
        }

        static ClientWithExecutor withExecutor(HttpClient client, ExecutorService service) {
            return new ClientWithExecutor(client, service);
        }
    }

    // A supplier of ClientCloseable
    sealed interface ClientProvider extends Supplier<ClientCloseable> {

        ClientCloseable get();

        // a ClientProvider that returns reusable clients wrapping the given clieny
        record ReusableClientProvider(HttpClient client) implements ClientProvider {
            @Override
            public ClientCloseable get() {
                return ClientCloseable.reusable(client);
            }
        }

        // A ClientProvider that builds a new ClientWithExecutor for every call to get()
        record ClientBuilder(HttpClient.Builder builder) implements ClientProvider {
            ClientCloseable build() {
                int id = IDS.getAndIncrement();
                ExecutorService virtualExecutor = Executors.newThreadPerTaskExecutor(Thread.ofVirtual()
                        .name("HttpClient-" + id + "-Worker", 0).factory());
                builder.executor(virtualExecutor);
                return ClientCloseable.withExecutor(builder.build(), virtualExecutor);
            }

            public ClientBuilder localAddress(InetAddress localAddress) {
                builder.localAddress(localAddress);
                return this;
            }

            public ClientProvider provider() { return this; }

            @Override
            public ClientCloseable get() { return build(); }
        }

        static ReusableClientProvider reusable(HttpClient client) {
            return new ReusableClientProvider(client);
        }

        static ClientBuilder builder(HttpClient.Builder builder) {
            return new ClientBuilder(builder);
        }
    }




    private static ClientProvider.ClientBuilder newBuilder(boolean configureClientSSL) {
        var builder = HttpClient.newBuilder();
        // don't let proxies interfere with the client addresses received on the
        // HTTP request, by the server side handler used in this test.
        builder.proxy(HttpClient.Builder.NO_PROXY);
        if (configureClientSSL) {
            builder.sslContext(sslContext);
        }
        return ClientProvider.builder(builder);
    }

    /**
     * Sends a GET request using the {@code client} and expects a 200 response.
     * The returned response body is then tested to see if the client address
     * seen by the server side handler is the same one as that is set on the
     * {@code client}
     */
    @Test(dataProvider = "params")
    public void testSend(ClientProvider clientProvider, URI requestURI, InetAddress localAddress) throws Exception {
        try (var c = clientProvider.get()) {
            HttpClient client = c.client();
            System.out.println("Testing using a HTTP client " + client.version() + " with local address " + localAddress
                    + " against request URI " + requestURI);
            // GET request
            var req = HttpRequest.newBuilder(requestURI).build();
            var resp = client.send(req, HttpResponse.BodyHandlers.ofByteArray());
            Assert.assertEquals(resp.statusCode(), 200, "Unexpected status code");
            // verify the address only if a specific one was set on the client
            if (localAddress != null && !localAddress.isAnyLocalAddress()) {
                Assert.assertEquals(resp.body(), localAddress.getAddress(),
                        "Unexpected client address seen by the server handler");
            }
        }
    }

    /**
     * Sends a GET request using the {@code sendAsync} method on the {@code client} and
     * expects a 200 response. The returned response body is then tested to see if the client address
     * seen by the server side handler is the same one as that is set on the
     * {@code client}
     */
    @Test(dataProvider = "params")
    public void testSendAsync(ClientProvider clientProvider, URI requestURI, InetAddress localAddress) throws Exception {
        try (var c = clientProvider.get()) {
            HttpClient client = c.client();
            System.out.println("Testing using a HTTP client " + client.version()
                    + " with local address " + localAddress
                    + " against request URI " + requestURI);
            // GET request
            var req = HttpRequest.newBuilder(requestURI).build();
            var cf = client.sendAsync(req,
                    HttpResponse.BodyHandlers.ofByteArray());
            var resp = cf.get();
            Assert.assertEquals(resp.statusCode(), 200, "Unexpected status code");
            // verify the address only if a specific one was set on the client
            if (localAddress != null && !localAddress.isAnyLocalAddress()) {
                Assert.assertEquals(resp.body(), localAddress.getAddress(),
                        "Unexpected client address seen by the server handler");
            }
        }
    }

    /**
     * Invokes the {@link #testSend} and {@link #testSendAsync}
     * tests, concurrently in multiple threads to verify that the correct local address
     * is used when multiple concurrent threads are involved in sending requests from
     * the {@code client}
     */
    @Test(dataProvider = "params")
    public void testMultiSendRequests(ClientProvider clientProvider,
                                      URI requestURI,
                                      InetAddress localAddress) throws Exception {
        int numThreads = 4;
        ExecutorService executor = Executors.newFixedThreadPool(numThreads);
        List<Future<Void>> taskResults = new ArrayList<>();
        try (var c = clientProvider.get()) {
            // prevents testSend/testSendAsync from closing the client
            ClientProvider client = ClientProvider.reusable(c.client());
            for (int i = 0; i < numThreads; i++) {
                final var currentIdx = i;
                var f = executor.submit(new Callable<Void>() {
                    @Override
                    public Void call() throws Exception {
                        // test some for send and some for sendAsync
                        if (currentIdx % 2 == 0) {
                            testSend(client, requestURI, localAddress);
                        } else {
                            testSendAsync(client, requestURI, localAddress);
                        }
                        return null;
                    }
                });
                taskResults.add(f);
            }
            // wait for results
            for (var r : taskResults) {
                r.get();
            }
        } finally {
            executor.shutdownNow();
        }
    }
}
