/*
 * Copyright (c) 2015, 2017, 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 8087112
 * @modules jdk.incubator.httpclient
 *          java.logging
 *          jdk.httpserver
 * @library /lib/testlibrary/
 * @compile ../../../com/sun/net/httpserver/LogFilter.java
 * @compile ../../../com/sun/net/httpserver/EchoHandler.java
 * @compile ../../../com/sun/net/httpserver/FileServerHandler.java
 * @build LightWeightHttpServer
 * @build jdk.testlibrary.SimpleSSLContext
 * @run testng/othervm RequestBodyTest
 */

import java.io.*;
import java.net.URI;
import jdk.incubator.http.HttpClient;
import jdk.incubator.http.HttpRequest;
import jdk.incubator.http.HttpResponse;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Supplier;
import javax.net.ssl.SSLContext;
import jdk.testlibrary.FileUtils;
import static java.nio.charset.StandardCharsets.*;
import static java.nio.file.StandardOpenOption.*;
import static jdk.incubator.http.HttpRequest.BodyProcessor.*;
import static jdk.incubator.http.HttpResponse.BodyHandler.*;

import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.*;

public class RequestBodyTest {

    static final String fileroot = System.getProperty("test.src") + "/docs";
    static final String midSizedFilename = "/files/notsobigfile.txt";
    static final String smallFilename = "/files/smallfile.txt";

    HttpClient client;
    ExecutorService exec = Executors.newCachedThreadPool();
    String httpURI;
    String httpsURI;

    enum RequestBody {
        BYTE_ARRAY,
        BYTE_ARRAY_OFFSET,
        BYTE_ARRAYS,
        FILE,
        INPUTSTREAM,
        STRING,
        STRING_WITH_CHARSET
    }

    enum ResponseBody {
        BYTE_ARRAY,
        BYTE_ARRAY_CONSUMER,
        DISCARD,
        FILE,
        FILE_WITH_OPTION,
        STRING,
        STRING_WITH_CHARSET,
    }

    @BeforeTest
    public void setup() throws Exception {
        LightWeightHttpServer.initServer();
        httpURI = LightWeightHttpServer.httproot + "echo/foo";
        httpsURI = LightWeightHttpServer.httpsroot + "echo/foo";

        SSLContext ctx = LightWeightHttpServer.ctx;
        client = HttpClient.newBuilder()
                           .sslContext(ctx)
                           .version(HttpClient.Version.HTTP_1_1)
                           .followRedirects(HttpClient.Redirect.ALWAYS)
                           .executor(exec)
                           .build();
    }

    @AfterTest
    public void teardown() throws Exception {
        exec.shutdownNow();
        LightWeightHttpServer.stop();
    }

    @DataProvider
    public Object[][] exchanges() throws Exception {
        List<Object[]> values = new ArrayList<>();

        for (boolean async : new boolean[] { false, true })
            for (String uri : new String[] { httpURI, httpsURI })
                for (String file : new String[] { smallFilename, midSizedFilename })
                    for (RequestBody requestBodyType : RequestBody.values())
                        for (ResponseBody responseBodyType : ResponseBody.values())
                            values.add(new Object[]
                                {uri, requestBodyType, responseBodyType, file, async});

        return values.stream().toArray(Object[][]::new);
    }

    @Test(dataProvider = "exchanges")
    void exchange(String target,
                  RequestBody requestBodyType,
                  ResponseBody responseBodyType,
                  String file,
                  boolean async)
        throws Exception
    {
        Path filePath = Paths.get(fileroot + file);
        URI uri = new URI(target);

        HttpRequest request = createRequest(uri, requestBodyType, filePath);

        checkResponse(client, request, requestBodyType, responseBodyType, filePath, async);
    }

    static final int DEFAULT_OFFSET = 10;
    static final int DEFAULT_LENGTH = 1000;

    HttpRequest createRequest(URI uri,
                              RequestBody requestBodyType,
                              Path file)
        throws IOException
    {
        HttpRequest.Builder rb =  HttpRequest.newBuilder(uri);

        String filename = file.toFile().getAbsolutePath();
        byte[] fileAsBytes = getFileBytes(filename);
        String fileAsString = new String(fileAsBytes, UTF_8);

        switch (requestBodyType) {
            case BYTE_ARRAY:
                rb.POST(fromByteArray(fileAsBytes));
                break;
            case BYTE_ARRAY_OFFSET:
                rb.POST(fromByteArray(fileAsBytes, DEFAULT_OFFSET, DEFAULT_LENGTH));
                break;
            case BYTE_ARRAYS:
                Iterable<byte[]> iterable = Arrays.asList(fileAsBytes);
                rb.POST(fromByteArrays(iterable));
                break;
            case FILE:
                rb.POST(fromFile(file));
                break;
            case INPUTSTREAM:
                rb.POST(fromInputStream(fileInputStreamSupplier(file)));
                break;
            case STRING:
                rb.POST(fromString(fileAsString));
                break;
            case STRING_WITH_CHARSET:
                rb.POST(fromString(new String(fileAsBytes), Charset.defaultCharset()));
                break;
            default:
                throw new AssertionError("Unknown request body:" + requestBodyType);
        }
        return rb.build();
    }

    void checkResponse(HttpClient client,
                       HttpRequest request,
                       RequestBody requestBodyType,
                       ResponseBody responseBodyType,
                       Path file,
                       boolean async)
        throws InterruptedException, IOException
    {
        String filename = file.toFile().getAbsolutePath();
        byte[] fileAsBytes = getFileBytes(filename);
        if (requestBodyType == RequestBody.BYTE_ARRAY_OFFSET) {
            // Truncate the expected response body, if only a portion was sent
            fileAsBytes = Arrays.copyOfRange(fileAsBytes,
                                             DEFAULT_OFFSET,
                                             DEFAULT_OFFSET + DEFAULT_LENGTH);
        }
        String fileAsString = new String(fileAsBytes, UTF_8);
        Path tempFile = Paths.get("RequestBodyTest.tmp");
        FileUtils.deleteFileIfExistsWithRetry(tempFile);

        switch (responseBodyType) {
            case BYTE_ARRAY:
                HttpResponse<byte[]> bar = getResponse(client, request, asByteArray(), async);
                assertEquals(bar.statusCode(), 200);
                assertEquals(bar.body(), fileAsBytes);
                break;
            case BYTE_ARRAY_CONSUMER:
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                HttpResponse<Void> v = getResponse(client, request,
                        asByteArrayConsumer(o -> consumerBytes(o, baos) ), async);
                byte[] ba = baos.toByteArray();
                assertEquals(v.statusCode(), 200);
                assertEquals(ba, fileAsBytes);
                break;
            case DISCARD:
                Object o = new Object();
                HttpResponse<Object> or = getResponse(client, request, discard(o), async);
                assertEquals(or.statusCode(), 200);
                assertSame(or.body(), o);
                break;
            case FILE:
                HttpResponse<Path> fr = getResponse(client, request, asFile(tempFile), async);
                assertEquals(fr.statusCode(), 200);
                assertEquals(Files.size(tempFile), fileAsString.length());
                assertEquals(Files.readAllBytes(tempFile), fileAsBytes);
                break;
            case FILE_WITH_OPTION:
                fr = getResponse(client, request, asFile(tempFile, CREATE_NEW, WRITE), async);
                assertEquals(fr.statusCode(), 200);
                assertEquals(Files.size(tempFile), fileAsString.length());
                assertEquals(Files.readAllBytes(tempFile), fileAsBytes);
                break;
            case STRING:
                HttpResponse<String> sr = getResponse(client, request, asString(), async);
                assertEquals(sr.statusCode(), 200);
                assertEquals(sr.body(), fileAsString);
                break;
            case STRING_WITH_CHARSET:
                HttpResponse<String> r = getResponse(client, request, asString(StandardCharsets.UTF_8), async);
                assertEquals(r.statusCode(), 200);
                assertEquals(r.body(), fileAsString);
                break;
            default:
                throw new AssertionError("Unknown response body:" + responseBodyType);
        }
    }

    static <T> HttpResponse<T> getResponse(HttpClient client,
                                           HttpRequest request,
                                           HttpResponse.BodyHandler<T> handler,
                                           boolean async)
        throws InterruptedException, IOException
    {
        if (!async)
            return client.send(request, handler);
        else
            return client.sendAsync(request, handler).join();
    }

    static byte[] getFileBytes(String path) throws IOException {
        try (FileInputStream fis = new FileInputStream(path);
             BufferedInputStream bis = new BufferedInputStream(fis);
             ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            bis.transferTo(baos);
            return baos.toByteArray();
        }
    }

    static Supplier<FileInputStream> fileInputStreamSupplier(Path f) {
        return new Supplier<>() {
            Path file = f;
            @Override
            public FileInputStream get() {
                try {
                    return new FileInputStream(file.toFile());
                } catch (FileNotFoundException x) {
                    throw new UncheckedIOException(x);
                }
            }
        };
    }

    static void consumerBytes(Optional<byte[]> bytes, ByteArrayOutputStream baos) {
        try {
            if (bytes.isPresent())
                baos.write(bytes.get());
        } catch (IOException x) {
            throw new UncheckedIOException(x);
        }
    }
}
