/*
 * Copyright (c) 2020, 2021, 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 8251496 8268960
 * @summary Tests for methods in Headers class
 * @modules jdk.httpserver/com.sun.net.httpserver:+open
 *          jdk.httpserver/sun.net.httpserver:+open
 * @library /test/lib
 * @build jdk.test.lib.net.URIBuilder
 * @run testng/othervm HeadersTest
 */

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import jdk.test.lib.net.URIBuilder;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import sun.net.httpserver.UnmodifiableHeaders;

import static java.net.http.HttpClient.Builder.NO_PROXY;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.assertThrows;
import static org.testng.Assert.assertTrue;

public class HeadersTest {

    static final Class<IllegalArgumentException> IAE = IllegalArgumentException.class;
    static final Class<IOException> IOE = IOException.class;
    static final Class<NullPointerException> NPE = NullPointerException.class;

    @Test
    public static void testDefaultConstructor() {
        var headers = new Headers();
        assertTrue(headers.isEmpty());
    }

    @Test
    public static void testNull() {
        final Headers h = new Headers();
        h.put("Foo", List.of("Bar"));

        final var mapNullKey = new HashMap<String, List<String>>();
        mapNullKey.put(null, List.of("Bar"));

        final var mapNullList = new HashMap<String, List<String>>();
        mapNullList.put("Foo", null);

        final var listWithNull = new LinkedList<String>();
        listWithNull.add(null);

        final var mapNullInList = new HashMap<String, List<String>>();
        mapNullInList.put("Foo", listWithNull);

        assertThrows(NPE, () -> h.add(null, "Bar"));
        assertThrows(NPE, () -> h.add("Foo", null));

        assertThrows(NPE, () -> h.compute(null, (k, v) -> List.of("Bar")));
        assertThrows(NPE, () -> h.compute("Foo", (k, v) -> listWithNull));

        assertThrows(NPE, () -> h.computeIfAbsent(null, (k) -> List.of("Bar")));
        assertThrows(NPE, () -> h.computeIfAbsent("Foo-foo", (k) -> listWithNull));

        assertThrows(NPE, () -> h.computeIfPresent(null, (k, v) -> List.of("Bar")));
        assertThrows(NPE, () -> h.computeIfPresent("Foo", (k, v) -> listWithNull));

        assertThrows(NPE, () -> h.containsKey(null));

        assertThrows(NPE, () -> h.containsValue(null));

        assertThrows(NPE, () -> h.get(null));

        assertThrows(NPE, () -> h.getFirst(null));

        assertThrows(NPE, () -> h.getOrDefault(null, List.of("Bar")));

        assertThrows(NPE, () -> h.merge(null, List.of("Bar"), (k, v) -> List.of("Bar")));
        assertThrows(NPE, () -> h.merge("Foo-foo", null, (k, v) -> List.of("Bar")));
        assertThrows(NPE, () -> h.merge("Foo-foo", listWithNull, (k, v) -> List.of("Bar")));
        assertThrows(NPE, () -> h.merge("Foo", List.of("Bar"), (k, v) -> listWithNull));

        assertThrows(NPE, () -> h.put(null, List.of("Bar")));
        assertThrows(NPE, () -> h.put("Foo", null));
        assertThrows(NPE, () -> h.put("Foo", listWithNull));

        assertThrows(NPE, () -> h.putAll(mapNullKey));
        assertThrows(NPE, () -> h.putAll(mapNullList));
        assertThrows(NPE, () -> h.putAll(mapNullInList));

        assertThrows(NPE, () -> h.putIfAbsent(null, List.of("Bar")));
        assertThrows(NPE, () -> h.putIfAbsent("Foo-foo", null));
        assertThrows(NPE, () -> h.putIfAbsent("Foo-foo", listWithNull));

        assertThrows(NPE, () -> h.remove(null));

        assertThrows(NPE, () -> h.remove(null, List.of("Bar")));

        assertThrows(NPE, () -> h.replace(null, List.of("Bar")));
        assertThrows(NPE, () -> h.replace("Foo", null));
        assertThrows(NPE, () -> h.replace("Foo", listWithNull));

        assertThrows(NPE, () -> h.replace(null, List.of("Bar"), List.of("Bar")));
        assertThrows(NPE, () -> h.replace("Foo", List.of("Bar"), null));
        assertThrows(NPE, () -> h.replace("Foo", List.of("Bar"), listWithNull));

        assertThrows(NPE, () -> h.replaceAll((k, v) -> listWithNull));
        assertThrows(NPE, () -> h.replaceAll((k, v) -> null));

        assertThrows(NPE, () -> h.set(null, "Bar"));
        assertThrows(NPE, () -> h.set("Foo", null));
    }

    @DataProvider
    public Object[][] responseHeaders() {
        final var listWithNull = new LinkedList<String>();
        listWithNull.add(null);
        return new Object[][] {
                {null,  List.of("Bar")},
                {"Foo", null},
                {"Foo", listWithNull}
        };
    }

    /**
     * Confirms HttpExchange::sendResponseHeaders throws NPE if response headers
     * contain a null key or value.
     */
    @Test(dataProvider = "responseHeaders")
    public void testNullResponseHeaders(String headerKey, List<String> headerVal)
            throws Exception {
        var handler = new Handler(headerKey, headerVal);
        var server = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0);
        server.createContext("/", handler);
        server.start();
        try {
            var client = HttpClient.newBuilder().proxy(NO_PROXY).build();
            var request = HttpRequest.newBuilder(uri(server, "")).build();
            assertThrows(IOE, () -> client.send(request, HttpResponse.BodyHandlers.ofString()));
            assertEquals(throwable.get().getClass(), NPE);
            assertTrue(Arrays.stream(throwable.get().getStackTrace())
                    .anyMatch(e -> e.getClassName().equals("sun.net.httpserver.HttpExchangeImpl")
                            || e.getMethodName().equals("sendResponseHeaders")));
        } finally {
            server.stop(0);
        }
    }

    private static CompletableFuture<Throwable> throwable = new CompletableFuture<>();

    private record Handler(String headerKey, List<String> headerVal) implements HttpHandler {

        @Override
        public void handle(HttpExchange exchange) throws IOException {
            try (InputStream is = exchange.getRequestBody();
                 OutputStream os = exchange.getResponseBody()) {
                is.readAllBytes();
                var resp = "hello world".getBytes(StandardCharsets.UTF_8);
                putHeaders(exchange.getResponseHeaders(), headerKey, headerVal);
                try {
                    exchange.sendResponseHeaders(200, resp.length);
                } catch (Throwable t) {  // expect NPE
                    throwable.complete(t);
                    throw t;
                }
                os.write(resp);
            }
        }
    }

    private static URI uri(HttpServer server, String path) {
        return URIBuilder.newBuilder()
                .host("localhost")
                .port(server.getAddress().getPort())
                .scheme("http")
                .path("/" + path)
                .buildUnchecked();
    }

    /**
     * Sets headers reflectively to be able to set a null key or value.
     */
    private static void putHeaders(Headers headers,
                                   String headerKey,
                                   List<String> headerVal) {
        try {
            final var map = new HashMap<String, List<String>>();
            map.put(headerKey, headerVal);
            var mapField = Headers.class.getDeclaredField("map");
            mapField.setAccessible(true);
            mapField.set(headers, map);
        } catch (Exception e) {
            throw new RuntimeException("Could not set headers reflectively", e);
        }
    }

    @DataProvider
    public static Object[][] headerPairs() {
        final var h1 = new Headers();
        final var h2 = new Headers();
        final var h3 = new Headers();
        final var h4 = new Headers();
        final var h5 = new Headers();
        h1.put("Accept-Encoding", List.of("gzip, deflate"));
        h2.put("accept-encoding", List.of("gzip, deflate"));
        h3.put("AccePT-ENCoding", List.of("gzip, deflate"));
        h4.put("ACCept-EncodING", List.of("gzip, deflate"));
        h5.put("ACCEPT-ENCODING", List.of("gzip, deflate"));

        final var headers = List.of(h1, h2, h3, h4, h5);
        return headers.stream()  // cartesian product of headers
                .flatMap(header1 -> headers.stream().map(header2 -> new Headers[] { header1, header2 }))
                .toArray(Object[][]::new);
    }

    @Test(dataProvider = "headerPairs")
    public static void testEqualsAndHashCode(Headers h1, Headers h2) {
        // avoid testng's asserts(Map, Map) as they don't call Headers::equals
        assertTrue(h1.equals(h2), "Headers differ");
        assertEquals(h1.hashCode(), h2.hashCode(), "hashCode differ for "
                + List.of(h1, h2));
    }

    @Test
    public static void testEqualsMap() {
        final var h = new Headers();
        final var m = new HashMap<String, List<String>>();
        assertTrue(h.equals(m));
        assertTrue(m.equals(h));
        assertFalse(h.equals(null), "null cannot be equal to Headers");
    }

    @Test
    public static void testToString() {
        final var h = new Headers();
        h.put("Accept-Encoding", List.of("gzip, deflate"));
        assertTrue(h.toString().equals("Headers { {Accept-encoding=[gzip, deflate]} }"));
    }

    @Test
    public static void testPutAll() {
        final var h0 = new Headers();
        final var map = new HashMap<String, List<String>>();
        map.put("a", null);
        assertThrows(NPE, () -> h0.putAll(map));

        final var list = new ArrayList<String>();
        list.add(null);
        assertThrows(NPE, () -> h0.putAll(Map.of("a", list)));
        assertThrows(IAE, () -> h0.putAll(Map.of("a", List.of("\n"))));

        final var h1 = new Headers();
        h1.put("a", List.of("1"));
        h1.put("b", List.of("2"));
        final var h2 = new Headers();
        h2.putAll(Map.of("a", List.of("1"), "b", List.of("2")));
        assertTrue(h1.equals(h2));
    }

    @Test
    public static void testReplaceAll() {
        final var h1 = new Headers();
        h1.put("a", List.of("1"));
        h1.put("b", List.of("2"));
        final var list = new ArrayList<String>();
        list.add(null);
        assertThrows(NPE, () -> h1.replaceAll((k, v) -> list));
        assertThrows(IAE, () -> h1.replaceAll((k, v) -> List.of("\n")));

        h1.replaceAll((k, v) -> {
            String s = h1.get(k).get(0);
            return List.of(s+s);
        });
        final var h2 = new Headers();
        h2.put("a", List.of("11"));
        h2.put("b", List.of("22"));
        assertTrue(h1.equals(h2));
    }

    @Test
    public static void test1ArgConstructorNull() {
        assertThrows(NPE, () -> new Headers(null));
        {
            final var m = new HashMap<String, List<String>>();
            m.put(null, List.of("Bar"));
            assertThrows(NPE, () -> new Headers(m));
        }
        {
            final var m = new HashMap<String, List<String>>();
            m.put("Foo", null);
            assertThrows(NPE, () -> new Headers(m));
        }
        {
            final var m = new HashMap<String, List<String>>();
            final var list = new LinkedList<String>();
            list.add(null);
            m.put("Foo", list);
            assertThrows(NPE, () -> new Headers(m));
        }
    }

    @Test
    public static void test1ArgConstructor() {
        {
            var h = new Headers(new Headers());
            assertTrue(h.isEmpty());
        }
        {
            var h = new Headers(Map.of("Foo", List.of("Bar")));
            assertEquals(h.get("Foo"), List.of("Bar"));
            assertEquals(h.size(), 1);
        }
        {
            var h1 = new Headers(new UnmodifiableHeaders(new Headers()));
            assertTrue(h1.isEmpty());
            h1.put("Foo", List.of("Bar"));  // modifiable
            assertEquals(h1.get("Foo"), List.of("Bar"));
            assertEquals(h1.size(), 1);

            var h2 = new Headers(h1);
            assertEquals(h2.get("Foo"), List.of("Bar"));
            assertEquals(h2.size(), 1);

            assertEquals(h1, h2);
            h1.set("Foo", "Barbar");
            assertNotEquals(h1, h2);
        }
    }

    @Test
    public static void testMutableHeaders() {
        {
            var h = new Headers();
            h.add("Foo", "Bar");
            h.add("Foo", "Bazz");
            h.get("Foo").remove(0);
            h.remove("Foo");
            h.clear();
        }
        {
            var h = new Headers(Map.of("Foo", List.of("Bar")));
            h.get("Foo").add("Bazz");
            h.get("Foo").remove(0);
            h.remove("Foo");
            h.clear();
        }
    }

    @Test
    public static void testOfNull() {
        assertThrows(NPE, () -> Headers.of((String[])null));
        assertThrows(NPE, () -> Headers.of(null, "Bar"));
        assertThrows(NPE, () -> Headers.of("Foo", null));

        assertThrows(NPE, () -> Headers.of((Map<String, List<String>>) null));
        {
            final var m = new HashMap<String, List<String>>();
            m.put(null, List.of("Bar"));
            assertThrows(NPE, () -> Headers.of(m));
        }
        {
            final var m = new HashMap<String, List<String>>();
            m.put("Foo", null);
            assertThrows(NPE, () -> Headers.of(m));
        }
        {
            final var m = new HashMap<String, List<String>>();
            final var list = new LinkedList<String>();
            list.add(null);
            m.put("Foo", list);
            assertThrows(NPE, () -> Headers.of(m));
        }
    }

    @Test
    public static void testOf() {
        final var h = Headers.of("a", "1", "b", "2");
        assertEquals(h.size(), 2);
        List.of("a", "b").forEach(n -> assertTrue(h.containsKey(n)));
        List.of("1", "2").forEach(v -> assertTrue(h.containsValue(List.of(v))));
    }

    @Test
    public static void testOfEmpty() {
        for (var h : List.of(Headers.of(), Headers.of(new String[] { }))) {
            assertEquals(h.size(), 0);
            assertTrue(h.isEmpty());
        }
    }

    @Test
    public static void testOfNumberOfElements() {
        assertThrows(IAE, () -> Headers.of("a"));
        assertThrows(IAE, () -> Headers.of("a", "1", "b"));
    }

    @Test
    public static void testOfMultipleValues() {
        final var h = Headers.of("a", "1", "b", "1", "b", "2", "b", "3");
        assertEquals(h.size(), 2);
        List.of("a", "b").forEach(n -> assertTrue(h.containsKey(n)));
        List.of(List.of("1"), List.of("1", "2", "3")).forEach(v -> assertTrue(h.containsValue(v)));
    }

    // Immutability tests in UnmodifiableHeadersTest.java
}
