/*
 * Copyright (c) 2023, 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 8054022
 * @summary Verify that expect 100-continue doesn't hang
 * @library /test/lib
 * @run junit/othervm HttpURLConnectionExpectContinueTest
 * @run junit/othervm -Djava.net.preferIPv4Stack=true HttpURLConnectionExpectContinueTest
 * @run junit/othervm -Djava.net.preferIPv6Addresses=true HttpURLConnectionExpectContinueTest
 */

import jdk.test.lib.net.URIBuilder;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;

import static org.junit.jupiter.api.Assertions.assertTrue;

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class HttpURLConnectionExpectContinueTest {

    class Control {
        volatile ServerSocket serverSocket = null;
        volatile boolean stop = false;
        volatile boolean respondWith100Continue = false;
        volatile boolean write100ContinueTwice = false;
        volatile String response = null;
    }

    private Thread serverThread = null;
    private volatile Control control;
    static final Logger logger;

    static {
        logger = Logger.getLogger("sun.net.www.protocol.http.HttpURLConnection");
        logger.setLevel(Level.ALL);
        Logger.getLogger("").getHandlers()[0].setLevel(Level.ALL);
    }

    @BeforeAll
    public void startServerSocket() throws Exception {
        Control control = this.control = new Control();

        control.serverSocket = new ServerSocket();
        control.serverSocket.setReuseAddress(true);
        control.serverSocket.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
        Runnable runnable = () -> {
            while (!control.stop) {
                try {
                    Socket socket = control.serverSocket.accept();
                    InputStream inputStream = socket.getInputStream();
                    InputStreamReader inputStreamReader = new InputStreamReader(inputStream);

                    StringBuilder stringBuilder = new StringBuilder();

                    // Read initial request
                    byte b;
                    while (true) {
                        b = (byte) inputStreamReader.read();
                        stringBuilder.append((char) b);

                        if (stringBuilder.length() >= 4) {
                            char[] lastBytes = new char[4];
                            stringBuilder.getChars(
                                    stringBuilder.length() - 4,
                                    stringBuilder.length(), lastBytes, 0);
                            if (Arrays.equals(lastBytes, new char[]{'\r', '\n', '\r', '\n'})) {
                                break;
                            }
                        }
                    }

                    OutputStream outputStream = socket.getOutputStream();

                    String header = stringBuilder.toString();
                    String contentLengthString = "Content-Length:";

                    // send 100 continue responses if set by test
                    if (control.respondWith100Continue) {
                        outputStream.write("HTTP/1.1 100 Continue\r\n\r\n".getBytes());
                        outputStream.flush();
                        if (control.write100ContinueTwice) {
                            outputStream.write("HTTP/1.1 100 Continue\r\n\r\n".getBytes());
                            outputStream.flush();
                        }
                    }

                    // expect main request to be received
                    int idx = header.indexOf(contentLengthString);

                    if (idx >= 0) {
                        String substr = header.substring(idx + contentLengthString.length());
                        idx = substr.indexOf('\r');
                        substr = substr.substring(0, idx);
                        int contentLength = Integer.parseInt(substr.trim());

                        StringBuilder contentLengthBuilder = new StringBuilder();
                        for (int i = 0; i < contentLength; i++) {
                            b = (byte) inputStreamReader.read();
                            contentLengthBuilder.append((char) b);
                        }

                    } else {
                        StringBuilder contentLengthBuilder = new StringBuilder();
                        while (true) {
                            b = (byte) inputStreamReader.read();
                            contentLengthBuilder.append((char) b);

                            if (contentLengthBuilder.length() >= 2) {
                                char[] lastBytes = new char[2];
                                contentLengthBuilder.getChars(
                                        contentLengthBuilder.length() - 2,
                                        contentLengthBuilder.length(), lastBytes, 0);
                                if (Arrays.equals(lastBytes, new char[]{'\r', '\n'})) {
                                    String lengthInHex =
                                            contentLengthBuilder.substring(0, contentLengthBuilder.length() - 2);

                                    int contentLength = Integer.parseInt(lengthInHex, 16);
                                    char[] body = new char[contentLength];
                                    inputStreamReader.read(body);
                                    break;
                                    // normally we have to parse more data,
                                    // but for simplicity we expect no more chunks...
                                }
                            }
                        }
                    }

                    // send response
                    outputStream.write(control.response.getBytes());
                    outputStream.flush();
                } catch (SocketException e) {
                    // ignore
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        };
        serverThread = new Thread(runnable);
        serverThread.start();
    }

    @AfterAll
    public void stopServerSocket() throws Exception {
        Control control = this.control;
        control.stop = true;
        control.serverSocket.close();
        serverThread.join();
    }

    @Test
    public void testNonChunkedRequestAndNoExpect100ContinueResponse() throws Exception {
        String body = "testNonChunkedRequestAndNoExpect100ContinueResponse";
        Control control = this.control;
        control.response = "HTTP/1.1 200 OK\r\n" +
                "Connection: close\r\n" +
                "Content-Length: " + body.length() + "\r\n" +
                "\r\n" +
                body + "\r\n";
        control.respondWith100Continue = false;
        control.write100ContinueTwice = false;

        HttpURLConnection connection = createConnection();
        OutputStream outputStream = connection.getOutputStream();
        outputStream.write(body.getBytes());
        outputStream.close();

        int responseCode = connection.getResponseCode();
        String responseBody = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8).strip();
        System.err.println("response body: " + responseBody);
        assertTrue(responseCode == 200,
                String.format("Expected 200 response, instead received %s", responseCode));
        assertTrue(body.equals(responseBody),
                String.format("Expected response %s, instead received %s", body, responseBody));
    }

    @Test
    public void testNonChunkedRequestWithExpect100ContinueResponse() throws Exception {
        String body = "testNonChunkedRequestWithExpect100ContinueResponse";
        Control control = this.control;
        control.response = "HTTP/1.1 200 OK\r\n" +
                "Connection: close\r\n" +
                "Content-Length: " + body.length() + "\r\n" +
                "\r\n" +
                body + "\r\n";
        control.respondWith100Continue = true;
        control.write100ContinueTwice = false;

        HttpURLConnection connection = createConnection();
        OutputStream outputStream = connection.getOutputStream();
        outputStream.write(body.getBytes());
        outputStream.close();

        int responseCode = connection.getResponseCode();
        String responseBody = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8).strip();
        System.err.println("response body: " + responseBody);
        assertTrue(responseCode == 200,
                String.format("Expected 200 response, instead received %s", responseCode));
        assertTrue(body.equals(responseBody),
                String.format("Expected response %s, instead received %s", body, responseBody));
    }

    @Test
    public void testNonChunkedRequestWithDoubleExpect100ContinueResponse() throws Exception {
        String body = "testNonChunkedRequestWithDoubleExpect100ContinueResponse";
        Control control = this.control;
        control.response = "HTTP/1.1 200 OK\r\n" +
                "Connection: close\r\n" +
                "Content-Length: " + body.length() + "\r\n" +
                "\r\n" +
                body + "\r\n";
        control.respondWith100Continue = true;
        control.write100ContinueTwice = true;

        HttpURLConnection connection = createConnection();
        OutputStream outputStream = connection.getOutputStream();
        outputStream.write(body.getBytes());
        outputStream.close();

        int responseCode = connection.getResponseCode();
        String responseBody = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8).strip();
        System.err.println("response body: " + responseBody);
        assertTrue(responseCode == 200,
                String.format("Expected 200 response, instead received %s", responseCode));
        assertTrue(body.equals(responseBody),
                String.format("Expected response %s, instead received %s", body, responseBody));
    }

    @Test
    public void testChunkedRequestAndNoExpect100ContinueResponse() throws Exception {
        String body = "testChunkedRequestAndNoExpect100ContinueResponse";
        Control control = this.control;
        control.response = "HTTP/1.1 200 OK\r\n" +
                "Connection: close\r\n" +
                "Content-Length: " + body.length() + "\r\n" +
                "\r\n" +
                body + "\r\n";
        control.respondWith100Continue = false;
        control.write100ContinueTwice = false;

        HttpURLConnection connection = createConnection();
        connection.setChunkedStreamingMode(body.length() / 2);
        OutputStream outputStream = connection.getOutputStream();
        outputStream.write(body.getBytes());
        outputStream.close();

        int responseCode = connection.getResponseCode();
        String responseBody = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8).strip();
        System.err.println("response body: " + responseBody);
        assertTrue(responseCode == 200,
                String.format("Expected 200 response, instead received %s", responseCode));
        assertTrue(body.equals(responseBody),
                String.format("Expected response %s, instead received %s", body, responseBody));
    }

    @Test
    public void testChunkedRequestWithExpect100ContinueResponse() throws Exception {
        String body = "testChunkedRequestWithExpect100ContinueResponse";
        Control control = this.control;
        control.response = "HTTP/1.1 200 OK\r\n" +
                "Connection: close\r\n" +
                "Content-Length: " + body.length() + "\r\n" +
                "\r\n" +
                body + "\r\n";
        control.respondWith100Continue = true;
        control.write100ContinueTwice = false;

        HttpURLConnection connection = createConnection();
        connection.setChunkedStreamingMode(body.length() / 2);
        OutputStream outputStream = connection.getOutputStream();
        outputStream.write(body.getBytes());
        outputStream.close();

        int responseCode = connection.getResponseCode();
        String responseBody = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8).strip();
        System.err.println("response body: " + responseBody);
        assertTrue(responseCode == 200,
                String.format("Expected 200 response, instead received %s", responseCode));
        assertTrue(body.equals(responseBody),
                String.format("Expected response %s, instead received %s", body, responseBody));
    }

    @Test
    public void testChunkedRequestWithDoubleExpect100ContinueResponse() throws Exception {
        String body = "testChunkedRequestWithDoubleExpect100ContinueResponse";
        Control control = this.control;
        control.response = "HTTP/1.1 200 OK\r\n" +
                "Connection: close\r\n" +
                "Content-Length: " + body.length() + "\r\n" +
                "\r\n" +
                body + "\r\n";
        control.respondWith100Continue = true;
        control.write100ContinueTwice = true;

        HttpURLConnection connection = createConnection();
        connection.setChunkedStreamingMode(body.length() / 2);
        OutputStream outputStream = connection.getOutputStream();
        outputStream.write(body.getBytes());
        outputStream.close();

        int responseCode = connection.getResponseCode();
        String responseBody = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8).strip();
        System.err.println("response body: " + responseBody);
        assertTrue(responseCode == 200,
                String.format("Expected 200 response, instead received %s", responseCode));
        assertTrue(body.equals(responseBody),
                String.format("Expected response %s, instead received %s", body, responseBody));
    }

    @Test
    public void testFixedLengthRequestAndNoExpect100ContinueResponse() throws Exception {
        String body = "testFixedLengthRequestAndNoExpect100ContinueResponse";
        Control control = this.control;
        control.response = "HTTP/1.1 200 OK\r\n" +
                "Connection: close\r\n" +
                "Content-Length: " + body.length() + "\r\n" +
                "\r\n" +
                body + "\r\n";
        control.respondWith100Continue = false;
        control.write100ContinueTwice = false;

        HttpURLConnection connection = createConnection();
        connection.setFixedLengthStreamingMode(body.length());
        OutputStream outputStream = connection.getOutputStream();
        outputStream.write(body.getBytes());
        outputStream.close();

        int responseCode = connection.getResponseCode();
        String responseBody = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8).strip();
        System.err.println("response body: " + responseBody);
        assertTrue(responseCode == 200,
                String.format("Expected 200 response, instead received %s", responseCode));
        assertTrue(body.equals(responseBody),
                String.format("Expected response %s, instead received %s", body, responseBody));
    }

    @Test
    public void testFixedLengthRequestWithExpect100ContinueResponse() throws Exception {
        String body = "testFixedLengthRequestWithExpect100ContinueResponse";
        Control control = this.control;
        control.response = "HTTP/1.1 200 OK\r\n" +
                "Connection: close\r\n" +
                "Content-Length: " + body.length() + "\r\n" +
                "\r\n" +
                body + "\r\n";
        control.respondWith100Continue = true;
        control.write100ContinueTwice = false;

        HttpURLConnection connection = createConnection();
        connection.setFixedLengthStreamingMode(body.getBytes().length);
        OutputStream outputStream = connection.getOutputStream();
        outputStream.write(body.getBytes());
        outputStream.close();

        int responseCode = connection.getResponseCode();
        String responseBody = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8).strip();
        System.err.println("response body: " + responseBody);
        assertTrue(responseCode == 200,
                String.format("Expected 200 response, instead received %s", responseCode));
        assertTrue(body.equals(responseBody),
                String.format("Expected response %s, instead received %s", body, responseBody));
    }

    @Test
    public void testFixedLengthRequestWithDoubleExpect100ContinueResponse() throws Exception {
        String body = "testFixedLengthRequestWithDoubleExpect100ContinueResponse";
        Control control = this.control;
        control.response = "HTTP/1.1 200 OK\r\n" +
                "Connection: close\r\n" +
                "Content-Length: " + body.length() + "\r\n" +
                "\r\n" +
                body + "\r\n";
        control.respondWith100Continue = true;
        control.write100ContinueTwice = true;

        HttpURLConnection connection = createConnection();
        connection.setFixedLengthStreamingMode(body.getBytes().length);
        OutputStream outputStream = connection.getOutputStream();
        outputStream.write(body.getBytes());
        outputStream.close();

        int responseCode = connection.getResponseCode();
        String responseBody = new String(connection.getInputStream().readAllBytes(), StandardCharsets.UTF_8).strip();
        System.err.println("response body: " + responseBody);
        assertTrue(responseCode == 200,
                String.format("Expected 200 response, instead received %s", responseCode));
        assertTrue(body.equals(responseBody),
                String.format("Expected response %s, instead received %s", body, responseBody));
    }

    // Creates a connection with all the common settings used in each test
    private HttpURLConnection createConnection() throws Exception {
        URL url = URIBuilder.newBuilder()
                .scheme("http")
                .loopback()
                .port(control.serverSocket.getLocalPort())
                .toURL();

        HttpURLConnection connection = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
        connection.setDoOutput(true);
        connection.setReadTimeout(5000);
        connection.setUseCaches(false);
        connection.setInstanceFollowRedirects(false);
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Connection", "Close");
        connection.setRequestProperty("Expect", "100-Continue");

        return connection;
    }
}
