/*
 * Copyright (c) 2022, 2024, 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.
 */

/*
 * @test
 * @bug 8263031
 * @summary Tests that the HttpClient can correctly receive a Push Promise
 *          Frame with the END_HEADERS flag unset followed by one or more
 *          Continuation Frames.
 * @library /test/lib /test/jdk/java/net/httpclient/lib
 * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.http2.Http2TestServer
 *        jdk.httpclient.test.lib.http2.BodyOutputStream
 *        jdk.httpclient.test.lib.http2.OutgoingPushPromise
 * @run testng/othervm PushPromiseContinuation
 */


import javax.net.ssl.SSLSession;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ProtocolException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpHeaders;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.BiPredicate;

import jdk.httpclient.test.lib.http2.Http2TestServer;
import jdk.httpclient.test.lib.http2.Http2TestExchange;
import jdk.httpclient.test.lib.http2.Http2TestExchangeImpl;
import jdk.httpclient.test.lib.http2.Http2Handler;
import jdk.httpclient.test.lib.http2.BodyOutputStream;
import jdk.httpclient.test.lib.http2.OutgoingPushPromise;
import jdk.httpclient.test.lib.http2.Http2TestServerConnection;

import jdk.internal.net.http.common.HttpHeadersBuilder;
import jdk.internal.net.http.frame.ContinuationFrame;
import jdk.internal.net.http.frame.HeaderFrame;

import org.testng.TestException;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.testng.Assert.*;


public class PushPromiseContinuation {

    static volatile HttpHeaders testHeaders;
    static volatile HttpHeadersBuilder testHeadersBuilder;
    static volatile int continuationCount;
    static final String mainPromiseBody = "Main Promise Body";
    static final String mainResponseBody = "Main Response Body";
    Http2TestServer server;
    URI uri;

    // Set up simple client-side push promise handler
    ConcurrentMap<HttpRequest, CompletableFuture<HttpResponse<String>>> pushPromiseMap = new ConcurrentHashMap<>();
    HttpResponse.PushPromiseHandler<String> pph = (initial, pushRequest, acceptor) -> {
        HttpResponse.BodyHandler<String> s = HttpResponse.BodyHandlers.ofString(UTF_8);
        pushPromiseMap.put(pushRequest, acceptor.apply(s));
    };

    @BeforeMethod
    public void beforeMethod() {
        pushPromiseMap = new ConcurrentHashMap<>();
    }

    @BeforeTest
    public void setup() throws Exception {
        server = new Http2TestServer(false, 0);
        server.addHandler(new ServerPushHandler(), "/");

        // Need to have a custom exchange supplier to manage the server's push
        // promise with continuation flow
        server.setExchangeSupplier(Http2PushPromiseContinuationExchangeImpl::new);

        System.err.println("PushPromiseContinuation: Server listening on port " + server.getAddress().getPort());
        server.start();
        int port = server.getAddress().getPort();
        uri = new URI("http://localhost:" + port + "/");
    }

    @AfterTest
    public void teardown() {
        pushPromiseMap = null;
        server.stop();
    }

    /**
     * Tests that when the client receives PushPromise Frame with the END_HEADERS
     * flag set to 0x0 and subsequently receives a continuation frame, no exception
     * is thrown and all headers from the PushPromise and Continuation Frames sent
     * by the server arrive at the client.
     */
    @Test
    public void testOneContinuation() {
        continuationCount = 1;
        HttpClient client = HttpClient.newHttpClient();

        // Carry out request
        HttpRequest hreq = HttpRequest.newBuilder(uri).version(HttpClient.Version.HTTP_2).GET().build();
        CompletableFuture<HttpResponse<String>> cf =
                client.sendAsync(hreq, HttpResponse.BodyHandlers.ofString(UTF_8), pph);
        HttpResponse<String> resp = cf.join();

        // Verify results
        verify(resp);
    }

    /**
     * Same as above, but tests for the case where two Continuation Frames are sent
     * with the END_HEADERS flag set only on the last frame.
     */
    @Test
    public void testTwoContinuations() {
        continuationCount = 2;
        HttpClient client = HttpClient.newHttpClient();

        // Carry out request
        HttpRequest hreq = HttpRequest.newBuilder(uri).version(HttpClient.Version.HTTP_2).GET().build();
        CompletableFuture<HttpResponse<String>> cf =
                client.sendAsync(hreq, HttpResponse.BodyHandlers.ofString(UTF_8), pph);
        HttpResponse<String> resp = cf.join();

        // Verify results
        verify(resp);
    }

    @Test
    public void testThreeContinuations() {
        continuationCount = 3;
        HttpClient client = HttpClient.newHttpClient();

        // Carry out request
        HttpRequest hreq = HttpRequest.newBuilder(uri).version(HttpClient.Version.HTTP_2).GET().build();
        CompletableFuture<HttpResponse<String>> cf =
                client.sendAsync(hreq, HttpResponse.BodyHandlers.ofString(UTF_8), pph);
        HttpResponse<String> resp = cf.join();

        // Verify results
        verify(resp);
    }

    @Test
    public void testSendHeadersOnPushPromiseStream() throws Exception {
        // This test server sends a push promise that should be followed by a continuation but
        // incorrectly sends on Response Headers while the client awaits the continuation.
        Http2TestServer faultyServer = new Http2TestServer(false, 0);
        faultyServer.addHandler(new ServerPushHandler(), "/");
        faultyServer.setExchangeSupplier(Http2PushPromiseHeadersExchangeImpl::new);
        System.err.println("PushPromiseContinuation: FaultyServer listening on port " + faultyServer.getAddress().getPort());
        faultyServer.start();

        int faultyPort = faultyServer.getAddress().getPort();
        URI faultyUri = new URI("http://localhost:" + faultyPort + "/");

        HttpClient client = HttpClient.newHttpClient();
        // Server is making a request to an incorrect URI
        HttpRequest hreq = HttpRequest.newBuilder(faultyUri).version(HttpClient.Version.HTTP_2).GET().build();
        CompletableFuture<HttpResponse<String>> cf =
                client.sendAsync(hreq, HttpResponse.BodyHandlers.ofString(UTF_8), pph);

        CompletionException t = expectThrows(CompletionException.class, () -> cf.join());
        assertEquals(t.getCause().getClass(), ProtocolException.class,
                "Expected a ProtocolException but got " + t.getCause());
        System.err.println("Client received the following expected exception: " + t.getCause());
        faultyServer.stop();
    }

    private void verify(HttpResponse<String> resp) {
        assertEquals(resp.statusCode(), 200);
        assertEquals(resp.body(), mainResponseBody);
        if (pushPromiseMap.size() > 1) {
            System.err.println(pushPromiseMap.entrySet());
            throw new TestException("Results map size is greater than 1");
        } else {
            // This will only iterate once
            for (HttpRequest r : pushPromiseMap.keySet()) {
                HttpResponse<String> serverPushResp = pushPromiseMap.get(r).join();
                // Received headers should be the same as the combined PushPromise
                // frame headers combined with the Continuation frame headers
                assertEquals(testHeaders, r.headers());
                // Check status code and push promise body are as expected
                assertEquals(serverPushResp.statusCode(), 200);
                assertEquals(serverPushResp.body(), mainPromiseBody);
            }
        }
    }

    static class Http2PushPromiseHeadersExchangeImpl extends Http2TestExchangeImpl {

        Http2PushPromiseHeadersExchangeImpl(int streamid, String method, HttpHeaders reqheaders,
                                            HttpHeadersBuilder rspheadersBuilder, URI uri, InputStream is,
                                            SSLSession sslSession, BodyOutputStream os,
                                            Http2TestServerConnection conn, boolean pushAllowed) {
            super(streamid, method, reqheaders, rspheadersBuilder, uri, is, sslSession, os, conn, pushAllowed);
        }


        @Override
        public void serverPush(URI uri, HttpHeaders headers, InputStream content) {
            HttpHeadersBuilder headersBuilder = new HttpHeadersBuilder();
            headersBuilder.setHeader(":method", "GET");
            headersBuilder.setHeader(":scheme", uri.getScheme());
            headersBuilder.setHeader(":authority", uri.getAuthority());
            headersBuilder.setHeader(":path", uri.getPath());
            for (Map.Entry<String,List<String>> entry : headers.map().entrySet()) {
                for (String value : entry.getValue())
                    headersBuilder.addHeader(entry.getKey(), value);
            }
            HttpHeaders combinedHeaders = headersBuilder.build();
            OutgoingPushPromise pp = new OutgoingPushPromise(streamid, uri, combinedHeaders, content);
            // Indicates to the client that a continuation should be expected
            pp.setFlag(0x0);
            try {
                conn.addToOutputQ(pp);
                // writeLoop will spin up thread to read the InputStream
            } catch (IOException ex) {
                System.err.println("TestServer: pushPromise exception: " + ex);
            }
        }
    }

    static class Http2PushPromiseContinuationExchangeImpl extends Http2TestExchangeImpl {

        HttpHeadersBuilder pushPromiseHeadersBuilder;
        List<ContinuationFrame> cfs;

        Http2PushPromiseContinuationExchangeImpl(int streamid, String method, HttpHeaders reqheaders,
                                                 HttpHeadersBuilder rspheadersBuilder, URI uri, InputStream is,
                                                 SSLSession sslSession, BodyOutputStream os,
                                                 Http2TestServerConnection conn, boolean pushAllowed) {
            super(streamid, method, reqheaders, rspheadersBuilder, uri, is, sslSession, os, conn, pushAllowed);
        }

        private void setPushHeaders(String name, String value) {
            pushPromiseHeadersBuilder.setHeader(name, value);
            testHeadersBuilder.setHeader(name, value);
        }

        private void assembleContinuations() {
            for (int i = 0; i < continuationCount; i++) {
                HttpHeadersBuilder builder = new HttpHeadersBuilder();
                for (int j = 0; j < 10; j++) {
                    String name = "x-cont-" + i + "-" + j;
                    builder.setHeader(name, "data_" + j);
                    testHeadersBuilder.setHeader(name, "data_" + j);
                }

                ContinuationFrame cf = new ContinuationFrame(streamid, 0x0, conn.encodeHeaders(builder.build()));
                // If this is the last Continuation Frame, set the END_HEADERS flag.
                if (i >= continuationCount - 1) {
                    cf.setFlag(HeaderFrame.END_HEADERS);
                }
                cfs.add(cf);
            }
        }

        @Override
        public void serverPush(URI uri, HttpHeaders headers, InputStream content) {
            pushPromiseHeadersBuilder = new HttpHeadersBuilder();
            testHeadersBuilder = new HttpHeadersBuilder();
            cfs = new ArrayList<>();

            setPushHeaders(":method", "GET");
            setPushHeaders(":scheme", uri.getScheme());
            setPushHeaders(":authority", uri.getAuthority());
            setPushHeaders(":path", uri.getPath());
            for (Map.Entry<String,List<String>> entry : headers.map().entrySet()) {
                for (String value : entry.getValue()) {
                    setPushHeaders(entry.getKey(), value);
                }
            }

            for (int i = 0; i < 10; i++) {
                setPushHeaders("x-push-header-" + i, "data_" + i);
            }

            // Create the Continuation Frame/s, done before Push Promise Frame for test purposes
            // as testHeaders contains all headers used in all frames
            assembleContinuations();

            HttpHeaders pushPromiseHeaders = pushPromiseHeadersBuilder.build();
            testHeaders = testHeadersBuilder.build();
            // Create the Push Promise Frame
            OutgoingPushPromise pp = new OutgoingPushPromise(streamid, uri, pushPromiseHeaders, content, cfs);

            // Indicates to the client that a continuation should be expected
            pp.setFlag(0x0);

            try {
                // Schedule push promise and continuation for sending
                conn.addToOutputQ(pp);
                System.err.println("Server: Scheduled a Push Promise to Send");
            } catch (IOException ex) {
                System.err.println("Server: pushPromise exception: " + ex);
            }
        }
    }

    static class ServerPushHandler implements Http2Handler {

        public void handle(Http2TestExchange exchange) throws IOException {
            System.err.println("Server: handle " + exchange);
            try (InputStream is = exchange.getRequestBody()) {
                is.readAllBytes();
            }

            if (exchange.serverPushAllowed()) {
                pushPromise(exchange);
            }

            // response data for the main response
            try (OutputStream os = exchange.getResponseBody()) {
                byte[] bytes = mainResponseBody.getBytes(UTF_8);
                exchange.sendResponseHeaders(200, bytes.length);
                os.write(bytes);
            }
        }

        static final BiPredicate<String,String> ACCEPT_ALL = (x, y) -> true;


        private void pushPromise(Http2TestExchange exchange) throws IOException {
            URI requestURI = exchange.getRequestURI();
            URI uri = requestURI.resolve("/promise");
            InputStream is = new ByteArrayInputStream(mainPromiseBody.getBytes(UTF_8));
            Map<String, List<String>> map = new HashMap<>();
            map.put("x-promise", List.of("promise-header"));
            HttpHeaders headers = HttpHeaders.of(map, ACCEPT_ALL);
            exchange.serverPush(uri, headers, is);
            System.err.println("Server: Push Promise complete");
        }
    }
}
