/*
 * Copyright (c) 2019, 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 8217264
 * @summary Tests that you can map an InputStream to a GZIPInputStream
 * @library /test/lib /test/jdk/java/net/httpclient/lib
 * @build jdk.test.lib.net.SimpleSSLContext jdk.httpclient.test.lib.common.HttpServerAdapters ReferenceTracker
 * @run testng/othervm GZIPInputStreamTest
 */

import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsServer;
import jdk.test.lib.net.SimpleSSLContext;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
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.net.http.HttpResponse.BodyHandler;
import java.net.http.HttpResponse.BodyHandlers;
import java.net.http.HttpResponse.BodySubscribers;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import jdk.httpclient.test.lib.common.HttpServerAdapters;
import jdk.httpclient.test.lib.http2.Http2TestServer;

import static java.lang.System.out;
import static java.net.http.HttpClient.Version.HTTP_1_1;
import static java.net.http.HttpClient.Version.HTTP_2;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.testng.Assert.assertEquals;

public class GZIPInputStreamTest implements HttpServerAdapters {

    SSLContext sslContext;
    HttpTestServer httpTestServer;    // HTTP/1.1    [ 4 servers ]
    HttpTestServer httpsTestServer;   // HTTPS/1.1
    HttpTestServer http2TestServer;   // HTTP/2 ( h2c )
    HttpTestServer https2TestServer;  // HTTP/2 ( h2  )
    String httpURI;
    String httpsURI;
    String http2URI;
    String https2URI;

    static final int ITERATION_COUNT = 3;
    // a shared executor helps reduce the amount of threads created by the test
    // this test will block if the executor doesn't have at least two threads.
    static final Executor executor = Executors.newFixedThreadPool(2);
    static final Executor singleThreadExecutor = Executors.newSingleThreadExecutor();

    public static final String LOREM_IPSUM =
            "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
                    + "Proin et lorem a sem faucibus finibus. "
                    + "Nam nisl nibh, elementum laoreet rutrum quis, lobortis at sem. "
                    + "Aenean purus libero, vehicula sed auctor ac, finibus commodo massa. "
                    + "Etiam dapibus nisl ex, viverra iaculis sapien suscipit sit amet. "
                    + "Phasellus fringilla id orci sit amet convallis. "
                    + "Nam suscipit tempor felis sed feugiat. "
                    + "Mauris quis viverra justo, vitae vulputate turpis. "
                    + "Ut eu orci eget ante faucibus volutpat quis quis urna. "
                    + "Ut porttitor mattis diam, ac sollicitudin ligula volutpat vel. "
                    + "Quisque pretium leo sed augue lacinia, eu mollis dui tempor.\n\n"
                    + "Nullam at mi porttitor, condimentum enim et, tristique felis. "
                    + "Nulla ante elit, interdum id ante ac, dignissim suscipit urna. "
                    + "Sed rhoncus felis eget placerat tincidunt. "
                    + "Duis pellentesque, eros et laoreet lacinia, urna arcu elementum metus, "
                    + "et tempor nibh ante vel odio. "
                    + "Donec et dolor posuere, sagittis libero sit amet, imperdiet ligula. "
                    + "Sed aliquam nulla congue bibendum hendrerit. "
                    + "Morbi ut tincidunt turpis. "
                    + "Nullam semper ipsum et sem imperdiet, sit amet commodo turpis euismod. "
                    + "Nullam aliquet metus id libero elementum, ut pulvinar urna gravida. "
                    + "Nullam non rhoncus diam. "
                    + "Mauris sagittis bibendum odio, sed accumsan sem ullamcorper ut.\n\n"
                    + "Proin malesuada nisl a quam dignissim rhoncus. "
                    + "Pellentesque vitae dui velit. "
                    + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
                    + "Vivamus sagittis magna id magna vestibulum, nec lacinia odio maximus. "
                    + "Nunc commodo, nisl non sagittis posuere, tortor ligula accumsan diam, "
                    + "a rhoncus augue velit quis enim. "
                    + "Nulla et dictum mauris. "
                    + "Vivamus et accumsan mauris, et tincidunt nunc.\n\n"
                    + "Nullam non pharetra lectus. "
                    + "Fusce lobortis sapien ante, quis egestas tellus tincidunt efficitur. "
                    + "Proin tempus mollis urna, sit amet congue diam eleifend in. "
                    + "Ut auctor metus ipsum, at porta turpis consectetur sed. "
                    + "Ut malesuada euismod massa, ut elementum nisi mattis eget. "
                    + "Donec ultrices vel dolor at convallis. "
                    + "Nunc eget felis nec nunc faucibus finibus. "
                    + "Curabitur nec auctor metus, sit amet tristique lorem. "
                    + "Donec tempus fringilla suscipit. Cras sit amet ante elit. "
                    + "Ut sodales sagittis eros quis cursus. "
                    + "Maecenas finibus ante quis euismod rutrum. "
                    + "Aenean scelerisque placerat nisi. "
                    + "Fusce porta, nibh vel efficitur sodales, urna eros consequat tellus, "
                    + "at fringilla ex justo in mi. "
                    + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
                    + "Morbi accumsan, justo nec tincidunt pretium, justo ex consectetur ante, "
                    + "nec euismod diam velit vitae quam.\n\n"
                    + "Vestibulum ante ipsum primis in faucibus orci luctus et "
                    + "ultrices posuere cubilia Curae; "
                    + "Praesent eget consequat nunc, vel dapibus nulla. "
                    + "Maecenas egestas luctus consectetur. "
                    + "Duis lacus risus, sollicitudin sit amet justo sed, "
                    + "ultrices facilisis sapien. "
                    + "Mauris eget fermentum risus. "
                    + "Suspendisse potenti. Nam at tempor risus. "
                    + "Quisque lacus augue, dictum vel interdum quis, interdum et mi. "
                    + "In purus mauris, pellentesque et lectus eget, condimentum pretium odio."
                    + " Donec imperdiet congue laoreet. "
                    + "Cras pharetra hendrerit purus ac efficitur. \n";



    @DataProvider(name = "variants")
    public Object[][] variants() {
        return new Object[][]{
                { httpURI,   false },
                { httpURI,   true },
                { httpsURI,  false },
                { httpsURI,  true },
                { http2URI,  false },
                { http2URI,  true },
                { https2URI, false },
                { https2URI, true },
        };
    }

    final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE;
    HttpClient newHttpClient() {
        return TRACKER.track(HttpClient.newBuilder()
                         .executor(executor)
                         .sslContext(sslContext)
                         .build());
    }

    HttpClient newSingleThreadClient() {
        return TRACKER.track(HttpClient.newBuilder()
                .executor(singleThreadExecutor)
                .sslContext(sslContext)
                .build());
    }

    HttpClient newInLineClient() {
        return TRACKER.track(HttpClient.newBuilder()
                .executor((r) -> r.run() )
                .sslContext(sslContext)
                .build());
    }

    @Test(dataProvider = "variants")
    public void testPlainSyncAsString(String uri, boolean sameClient) throws Exception {
        out.println("\nSmoke test: verify that the result we get from the server is correct.");
        out.println("Uses plain send() and `asString` to get the plain string.");
        out.println("Uses single threaded executor");
        HttpClient client = null;
        for (int i=0; i< ITERATION_COUNT; i++) {
            if (!sameClient || client == null)
                client = newSingleThreadClient(); // should work with 1 single thread

            HttpRequest req = HttpRequest.newBuilder(URI.create(uri +"/txt/LoremIpsum.txt"))
                    .build();
            BodyHandler<String> handler = BodyHandlers.ofString(UTF_8);
            HttpResponse<String> response = client.send(req, handler);
            String lorem = response.body();
            if (!LOREM_IPSUM.equals(lorem)) {
                out.println("Response doesn't match");
                out.println("[" + LOREM_IPSUM + "] != [" + lorem + "]");
                assertEquals(LOREM_IPSUM, lorem);
            } else {
                out.println("Received expected response.");
            }
        }
    }

    @Test(dataProvider = "variants")
    public void testPlainSyncAsInputStream(String uri, boolean sameClient) throws Exception {
        out.println("Uses plain send() and `asInputStream` - calls readAllBytes() from main thread");
        out.println("Uses single threaded executor");
        HttpClient client = null;
        for (int i=0; i< ITERATION_COUNT; i++) {
            if (!sameClient || client == null)
                client = newSingleThreadClient(); // should work with 1 single thread

            HttpRequest req = HttpRequest.newBuilder(URI.create(uri + "/txt/LoremIpsum.txt"))
                    .build();
            BodyHandler<InputStream> handler = BodyHandlers.ofInputStream();
            HttpResponse<InputStream> response = client.send(req, handler);
            String lorem = new String(response.body().readAllBytes(), UTF_8);
            if (!LOREM_IPSUM.equals(lorem)) {
                out.println("Response doesn't match");
                out.println("[" + LOREM_IPSUM + "] != [" + lorem + "]");
                assertEquals(LOREM_IPSUM, lorem);
            } else {
                out.println("Received expected response.");
            }
        }
    }

    @Test(dataProvider = "variants")
    public void testGZIPSyncAsInputStream(String uri, boolean sameClient) throws Exception {
        out.println("Uses plain send() and `asInputStream` - " +
                "creates GZIPInputStream and calls readAllBytes() from main thread");
        out.println("Uses single threaded executor");
        HttpClient client = null;
        for (int i=0; i< ITERATION_COUNT; i++) {
            if (!sameClient || client == null)
                client = newSingleThreadClient(); // should work with 1 single thread

            HttpRequest req = HttpRequest.newBuilder(URI.create(uri + "/gz/LoremIpsum.txt.gz"))
                    .build();
            BodyHandler<InputStream> handler = BodyHandlers.ofInputStream();
            HttpResponse<InputStream> response = client.send(req, handler);
            GZIPInputStream gz = new GZIPInputStream(response.body());
            String lorem = new String(gz.readAllBytes(), UTF_8);
            if (!LOREM_IPSUM.equals(lorem)) {
                out.println("Response doesn't match");
                out.println("[" + LOREM_IPSUM + "] != [" + lorem + "]");
                assertEquals(LOREM_IPSUM, lorem);
            } else {
                out.println("Received expected response.");
            }
        }
    }

    @Test(dataProvider = "variants")
    public void testGZIPSyncAsGZIPInputStream(String uri, boolean sameClient) throws Exception {
        out.println("Uses plain send() and a mapping subscriber to "+
                "create the GZIPInputStream. Calls readAllBytes() from main thread");
        out.println("Uses a fixed thread pool executor with 2 thread");
        HttpClient client = null;
        for (int i=0; i< ITERATION_COUNT; i++) {
            if (!sameClient || client == null)
                client = newHttpClient(); // needs at least 2 threads

            HttpRequest req = HttpRequest.newBuilder(URI.create(uri + "/gz/LoremIpsum.txt.gz"))
                    .build();
            // This is dangerous, because the finisher will block.
            // We support this, but the executor must have enough threads.
            BodyHandler<InputStream> handler = new GZIPBodyHandler();
            HttpResponse<InputStream> response = client.send(req, handler);
            String lorem = new String(response.body().readAllBytes(), UTF_8);
            if (!LOREM_IPSUM.equals(lorem)) {
                out.println("Response doesn't match");
                out.println("[" + LOREM_IPSUM + "] != [" + lorem + "]");
                assertEquals(LOREM_IPSUM, lorem);
            } else {
                out.println("Received expected response.");
            }
        }
    }

    @Test(dataProvider = "variants")
    public void testGZIPSyncAsGZIPInputStreamSupplier(String uri, boolean sameClient) throws Exception {
        out.println("Uses plain send() and a mapping subscriber to "+
                "create a Supplier<GZIPInputStream>. Calls Supplier.get() " +
                "and readAllBytes() from main thread");
        out.println("Uses a single threaded executor");
        HttpClient client = null;
        for (int i=0; i< ITERATION_COUNT; i++) {
            if (!sameClient || client == null)
                client = newSingleThreadClient(); // should work with 1 single thread

            HttpRequest req = HttpRequest.newBuilder(URI.create(uri + "/gz/LoremIpsum.txt.gz"))
                    .build();
            // This is dangerous, because the finisher will block.
            // We support this, but the executor must have enough threads.
            BodyHandler<Supplier<InputStream>> handler = new BodyHandler<Supplier<InputStream>>() {
                 public HttpResponse.BodySubscriber<Supplier<InputStream>> apply(
                         HttpResponse.ResponseInfo responseInfo)
                 {
                    String contentType = responseInfo.headers().firstValue("Content-Encoding")
                            .orElse("identity");
                    out.println("Content-Encoding: " + contentType);
                    if (contentType.equalsIgnoreCase("gzip")) {
                        // This is dangerous. Blocking in the mapping function can wedge the
                        // response. We do support it provided that there enough thread in
                        // the executor.
                        return BodySubscribers.mapping(BodySubscribers.ofInputStream(),
                                (is) -> (() -> {
                                    try {
                                        return new GZIPInputStream(is);
                                    } catch (IOException io) {
                                        throw new UncheckedIOException(io);
                                    }
                                }));
                    } else return BodySubscribers.mapping(BodySubscribers.ofInputStream(),
                            (is) -> (() -> is));
                }
            };
            HttpResponse<Supplier<InputStream>> response = client.send(req, handler);
            String lorem = new String(response.body().get().readAllBytes(), UTF_8);
            if (!LOREM_IPSUM.equals(lorem)) {
                out.println("Response doesn't match");
                out.println("[" + LOREM_IPSUM + "] != [" + lorem + "]");
                assertEquals(LOREM_IPSUM, lorem);
            } else {
                out.println("Received expected response.");
            }
        }
    }

    @Test(dataProvider = "variants")
    public void testPlainAsyncAsInputStreamBlocks(String uri, boolean sameClient) throws Exception {
        out.println("Uses sendAsync() and `asInputStream`. Registers a dependent action "+
                "that calls readAllBytes()");
        out.println("Uses a fixed thread pool executor with two threads");
        HttpClient client = null;
        for (int i=0; i< ITERATION_COUNT; i++) {
            if (!sameClient || client == null)
                client = newHttpClient(); // needs at least 2 threads

            HttpRequest req = HttpRequest.newBuilder(URI.create(uri + "/txt/LoremIpsum.txt"))
                    .build();
            BodyHandler<InputStream> handler = BodyHandlers.ofInputStream();
            CompletableFuture<HttpResponse<InputStream>> responseCF = client.sendAsync(req, handler);
            // This is dangerous. Blocking in the mapping function can wedge the
            // response. We do support it provided that there enough threads in
            // the executor.
            String lorem = responseCF.thenApply((r) -> {
                try {
                    return new String(r.body().readAllBytes(), UTF_8);
                } catch (IOException io) {
                    throw new UncheckedIOException(io);
                }
            }).join();
            if (!LOREM_IPSUM.equals(lorem)) {
                out.println("Response doesn't match");
                out.println("[" + LOREM_IPSUM + "] != [" + lorem + "]");
                assertEquals(LOREM_IPSUM, lorem);
            } else {
                out.println("Received expected response.");
            }
        }
    }

    @Test(dataProvider = "variants")
    public void testGZIPAsyncAsGZIPInputStreamBlocks(String uri, boolean sameClient) throws Exception {
        out.println("Uses sendAsync() and a mapping subscriber to create a GZIPInputStream. " +
                 "Registers a dependent action that calls readAllBytes()");
        out.println("Uses a fixed thread pool executor with two threads");
        HttpClient client = null;
        for (int i=0; i< ITERATION_COUNT; i++) {
            if (!sameClient || client == null)
                client = newHttpClient(); // needs at least 2 threads

            HttpRequest req = HttpRequest.newBuilder(URI.create(uri + "/gz/LoremIpsum.txt.gz"))
                    .build();
            BodyHandler<InputStream> handler = new GZIPBodyHandler();
            CompletableFuture<HttpResponse<InputStream>> responseCF = client.sendAsync(req, handler);
            // This is dangerous - we support this, but it can block
            // if there are not enough threads available.
            // Correct custom code should use thenApplyAsync instead.
            String lorem = responseCF.thenApply((r) -> {
                try {
                    return new String(r.body().readAllBytes(), UTF_8);
                } catch (IOException io) {
                    throw new UncheckedIOException(io);
                }
            }).join();
            if (!LOREM_IPSUM.equals(lorem)) {
                out.println("Response doesn't match");
                out.println("[" + LOREM_IPSUM + "] != [" + lorem + "]");
                assertEquals(LOREM_IPSUM, lorem);
            } else {
                out.println("Received expected response.");
            }
        }
    }

    @Test(dataProvider = "variants")
    public void testGZIPSyncAsGZIPInputStreamBlocks(String uri, boolean sameClient) throws Exception {
        out.println("Uses sendAsync() and a mapping subscriber to create a GZIPInputStream," +
                "which is mapped again using a mapping subscriber " +
                "to call readAllBytes() and map to String");
        out.println("Uses a fixed thread pool executor with two threads");
        HttpClient client = null;
        for (int i=0; i< ITERATION_COUNT; i++) {
            if (!sameClient || client == null)
                client = newHttpClient(); // needs at least 2 threads

            HttpRequest req = HttpRequest.newBuilder(URI.create(uri + "/gz/LoremIpsum.txt.gz"))
                    .build();
            // This is dangerous. Blocking in the mapping function can wedge the
            // response. We do support it provided that there enough thread in
            // the executor.
            BodyHandler<String> handler = new MappingBodyHandler<>(new GZIPBodyHandler(),
                    (InputStream is) ->  {
                        try {
                            return new String(is.readAllBytes(), UTF_8);
                        } catch(IOException io) {
                            throw new UncheckedIOException(io);
                        }
                    });
            HttpResponse<String> response = client.send(req, handler);
            String lorem = response.body();
            if (!LOREM_IPSUM.equals(lorem)) {
                out.println("Response doesn't match");
                out.println("[" + LOREM_IPSUM + "] != [" + lorem + "]");
                assertEquals(LOREM_IPSUM, lorem);
            } else {
                out.println("Received expected response.");
            }
        }
    }

    @Test(dataProvider = "variants")
    public void testGZIPSyncAsGZIPInputStreamSupplierInline(String uri, boolean sameClient) throws Exception {
        out.println("Uses plain send() and a mapping subscriber to "+
                "create a Supplier<GZIPInputStream>. Calls Supplier.get() " +
                "and readAllBytes() from main thread");
        out.println("Uses an inline executor (no threads)");
        HttpClient client = null;
        for (int i=0; i< ITERATION_COUNT; i++) {
            if (!sameClient || client == null)
                client = newInLineClient(); // should even work with no threads

            HttpRequest req = HttpRequest.newBuilder(URI.create(uri + "/gz/LoremIpsum.txt.gz"))
                    .build();
            // This is dangerous, because the finisher will block.
            // We support this, but the executor must have enough threads.
            BodyHandler<Supplier<InputStream>> handler = new BodyHandler<Supplier<InputStream>>() {
                public HttpResponse.BodySubscriber<Supplier<InputStream>> apply(
                        HttpResponse.ResponseInfo responseInfo)
                {
                    String contentType = responseInfo.headers().firstValue("Content-Encoding")
                            .orElse("identity");
                    out.println("Content-Encoding: " + contentType);
                    if (contentType.equalsIgnoreCase("gzip")) {
                        // This is dangerous. Blocking in the mapping function can wedge the
                        // response. We do support it provided that there enough thread in
                        // the executor.
                        return BodySubscribers.mapping(BodySubscribers.ofInputStream(),
                                (is) -> (() -> {
                                    try {
                                        return new GZIPInputStream(is);
                                    } catch (IOException io) {
                                        throw new UncheckedIOException(io);
                                    }
                                }));
                    } else return BodySubscribers.mapping(BodySubscribers.ofInputStream(),
                            (is) -> (() -> is));
                }
            };
            HttpResponse<Supplier<InputStream>> response = client.send(req, handler);
            String lorem = new String(response.body().get().readAllBytes(), UTF_8);
            if (!LOREM_IPSUM.equals(lorem)) {
                out.println("Response doesn't match");
                out.println("[" + LOREM_IPSUM + "] != [" + lorem + "]");
                assertEquals(LOREM_IPSUM, lorem);
            } else {
                out.println("Received expected response.");
            }
        }
    }

    static final class GZIPBodyHandler implements BodyHandler<InputStream> {
        @Override
        public HttpResponse.BodySubscriber<InputStream> apply(HttpResponse.ResponseInfo responseInfo) {
            String contentType = responseInfo.headers().firstValue("Content-Encoding")
                    .orElse("identity");
            out.println("Content-Encoding: " + contentType);
            if (contentType.equalsIgnoreCase("gzip")) {
                // This is dangerous. Blocking in the mapping function can wedge the
                // response. We do support it provided that there enough thread in
                // the executor.
                return BodySubscribers.mapping(BodySubscribers.ofInputStream(),
                        (is) -> {
                    try {
                        return new GZIPInputStream(is);
                    } catch (IOException io) {
                        throw new UncheckedIOException(io);
                    }
                });
            } else return BodySubscribers.ofInputStream();
        }
    }

    static final class MappingBodyHandler<T,U> implements BodyHandler<U> {
        final BodyHandler<T> upstream;
        final Function<? super T,? extends U> finisher;
        MappingBodyHandler(BodyHandler<T> upstream, Function<T,U> finisher) {
            this.upstream = upstream;
            this.finisher = finisher;
        }
        @Override
        public HttpResponse.BodySubscriber<U> apply(HttpResponse.ResponseInfo responseInfo) {
            return BodySubscribers.mapping(upstream.apply(responseInfo), finisher);
        }
    }

    static String serverAuthority(HttpServer server) {
        return InetAddress.getLoopbackAddress().getHostName() + ":"
                + server.getAddress().getPort();
    }

    @BeforeTest
    public void setup() throws Exception {
        sslContext = new SimpleSSLContext().get();
        if (sslContext == null)
            throw new AssertionError("Unexpected null sslContext");

        HttpTestHandler plainHandler = new LoremIpsumPlainHandler();
        HttpTestHandler gzipHandler  = new LoremIpsumGZIPHandler();

        // HTTP/1.1
        httpTestServer = HttpTestServer.create(HTTP_1_1);
        httpTestServer.addHandler(plainHandler, "/http1/chunk/txt");
        httpTestServer.addHandler(gzipHandler,  "/http1/chunk/gz");
        httpURI = "http://" + httpTestServer.serverAuthority() + "/http1/chunk";

        httpsTestServer = HttpTestServer.create(HTTP_1_1, sslContext);
        httpsTestServer.addHandler(plainHandler, "/https1/chunk/txt");
        httpsTestServer.addHandler(gzipHandler, "/https1/chunk/gz");
        httpsURI = "https://" + httpsTestServer.serverAuthority() + "/https1/chunk";

        // HTTP/2
        http2TestServer = HttpTestServer.create(HTTP_2);
        http2TestServer.addHandler(plainHandler, "/http2/chunk/txt");
        http2TestServer.addHandler(gzipHandler, "/http2/chunk/gz");
        http2URI = "http://" + http2TestServer.serverAuthority() + "/http2/chunk";

        https2TestServer = HttpTestServer.create(HTTP_2, sslContext);
        https2TestServer.addHandler(plainHandler, "/https2/chunk/txt");
        https2TestServer.addHandler(gzipHandler, "/https2/chunk/gz");
        https2URI = "https://" + https2TestServer.serverAuthority() + "/https2/chunk";

        httpTestServer.start();
        httpsTestServer.start();
        http2TestServer.start();
        https2TestServer.start();
    }

    @AfterTest
    public void teardown() throws Exception {
        Thread.sleep(100);
        AssertionError fail = TRACKER.check(500);
        try {
            httpTestServer.stop();
            httpsTestServer.stop();
            http2TestServer.stop();
            https2TestServer.stop();
        } finally {
            if (fail != null) {
                throw fail;
            }
        }
    }


    static class LoremIpsumPlainHandler implements HttpTestHandler {
        @Override
        public void handle(HttpTestExchange t) throws IOException {
            try {
                out.println("LoremIpsumPlainHandler received request to " + t.getRequestURI());
                t.getResponseHeaders().addHeader("Content-Encoding", "identity");
                t.sendResponseHeaders(200, -1);
                long size = 0;
                try (OutputStream os = t.getResponseBody()) {
                    for (String s : LOREM_IPSUM.split("\n")) {
                        byte[] buf = s.getBytes(StandardCharsets.UTF_8);
                        System.out.println("Writing " + (buf.length + 1) + " bytes...");
                        os.write(buf);
                        os.write('\n');
                        os.flush();
                        size += buf.length + 1;
                    }
                } finally {
                    System.out.println("Sent " + size + " bytes");
                }
            } catch (IOException | RuntimeException | Error e) {
                e.printStackTrace();
                throw e;
            }
        }
    }

    static class LoremIpsumGZIPHandler implements HttpTestHandler {
        @Override
        public void handle(HttpTestExchange t) throws IOException {
            try {
                out.println("LoremIpsumGZIPHandler received request to " + t.getRequestURI());
                t.getResponseHeaders().addHeader("Content-Encoding", "gzip");
                t.sendResponseHeaders(200, -1);
                long size = 0;
                try (GZIPOutputStream os =
                             new GZIPOutputStream(t.getResponseBody())) {
                    for (String s : LOREM_IPSUM.split("\n")) {
                        byte[] buf = s.getBytes(StandardCharsets.UTF_8);
                        System.out.println("Writing and compressing "
                                + (buf.length + 1) + " uncompressed bytes...");
                        os.write(buf);
                        os.write('\n');
                        os.flush();
                        size += buf.length + 1;
                    }
                } finally {
                    System.out.println("Sent and compressed " + size + " uncompressed bytes");
                }
            } catch (IOException | RuntimeException | Error e) {
                e.printStackTrace();
                throw e;
            }
        }
    }

}
