/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.catalina.servlets;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;

import org.apache.catalina.Context;
import org.apache.catalina.Wrapper;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.startup.TomcatBaseTest;
import org.apache.catalina.util.IOTools;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.HexUtils;
import org.apache.tomcat.util.http.FastHttpDateFormat;
import org.apache.tomcat.util.security.ConcurrentMessageDigest;

@RunWith(Parameterized.class)
public class TestDefaultServletRangeRequests extends TomcatBaseTest {

    @Parameterized.Parameters(name = "{index} rangeHeader [{0}], ifRangeHeader [{1}]")
    public static Collection<Object[]> parameters() {

        // Get the length of the file used for this test
        // It varies by platform due to line-endings
        File index = new File("test/webapp/index.html");
        long len = index.length();
        String strLen = Long.toString(len);
        String lastModified = FastHttpDateFormat.formatDate(index.lastModified());
        String weakETag = "W/\"" + strLen + "-" + Long.toString(index.lastModified()) + "\"";
        String strongETag = "\"\"";
        try (FileInputStream is = new FileInputStream(index)) {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            IOTools.flow(is, os);
            strongETag = "\"" + HexUtils.toHexString(ConcurrentMessageDigest.digestSHA256(os.toByteArray())) + "\"";
        } catch (Exception e) {
        }

        List<Object[]> parameterSets = new ArrayList<>();

        parameterSets.add(new Object[] { "", null, Integer.valueOf(200), strLen, "" });
        // Invalid
        parameterSets.add(new Object[] { "bytes", null, Integer.valueOf(416), "", "*/" + len });
        parameterSets.add(new Object[] { "bytes=", null, Integer.valueOf(416), "", "*/" + len });
        // Invalid with unknown type
        parameterSets.add(new Object[] { "unknown", null, Integer.valueOf(416), "", "*/" + len });
        parameterSets.add(new Object[] { "unknown=", null, Integer.valueOf(416), "", "*/" + len });
        // Invalid ranges
        parameterSets.add(new Object[] { "bytes=-", null, Integer.valueOf(416), "", "*/" + len });
        parameterSets.add(new Object[] { "bytes=10-b", null, Integer.valueOf(416), "", "*/" + len });
        parameterSets.add(new Object[] { "bytes=b-10", null, Integer.valueOf(416), "", "*/" + len });
        // Invalid ranges (out of range)
        parameterSets.add(new Object[] { "bytes=1000-2000", null, Integer.valueOf(416), "", "*/" + len });
        // Valid overlapping ranges (up to 2)
        parameterSets.add(new Object[] { "bytes=1-100, 30-50", null, Integer.valueOf(206), "", "30-50/" + len });
        parameterSets.add(new Object[] { "bytes=1-100, 90-150", null, Integer.valueOf(206), "", "1-100/" + len });
        // Invalid overlapping ranges (3 or more)
        parameterSets.add(new Object[] { "bytes=1-100, 30-50, 10-20", null, Integer.valueOf(416), "", "*/" + len });
        parameterSets.add(new Object[] { "bytes=1-100, 90-150, 10-20", null, Integer.valueOf(416), "", "*/" + len });
        // Invalid no equals
        parameterSets.add(new Object[] { "bytes 1-10", null, Integer.valueOf(416), "", "*/" + len });
        parameterSets.add(new Object[] { "bytes1-10", null, Integer.valueOf(416), "", "*/" + len });
        parameterSets.add(new Object[] { "bytes10-", null, Integer.valueOf(416), "", "*/" + len });
        parameterSets.add(new Object[] { "bytes-10", null, Integer.valueOf(416), "", "*/" + len });
        // Unknown types
        parameterSets.add(new Object[] { "unknown=1-2", null, Integer.valueOf(200), strLen, "" });
        parameterSets.add(new Object[] { "bytesX=1-2", null, Integer.valueOf(200), strLen, "" });
        parameterSets.add(new Object[] { "Xbytes=1-2", null, Integer.valueOf(200), strLen, "" });
        // Valid range
        parameterSets.add(new Object[] {
                "bytes=0-9", null, Integer.valueOf(206), "10", "0-9/" + len });
        parameterSets.add(new Object[] {
                "bytes=0-9,10-10", null, Integer.valueOf(206), null, "0-9/" + len });
        parameterSets.add(new Object[] {
                "bytes=-100", null, Integer.valueOf(206), "100", (len - 100) + "-" + (len - 1) + "/" + len });
        parameterSets.add(new Object[] {
                "bytes=100-", null, Integer.valueOf(206), "" + (len - 100), "100-" + (len - 1) + "/" + len });
        // Valid range (too much)
        parameterSets.add(new Object[] {
                "bytes=0-1000", null, Integer.valueOf(206), strLen, "0-" +  (len - 1) + "/" + len });
        parameterSets.add(new Object[] {
                "bytes=-1000", null, Integer.valueOf(206), strLen, "0-" + (len - 1) + "/" + len });
        // Lots of small ranges (test target has a little over 900 bytes. Exact length varies by platform."
        StringBuilder range = new StringBuilder();
        range.append("bytes=");
        int lastRange = 900;
        for (int i = 1; i < lastRange; i++) {
            range.append(i);
            range.append('-');
            range.append(i);
            range.append(',');
        }
        range.append(lastRange);
        range.append('-');
        range.append(lastRange);
        parameterSets.add(new Object[] { range.toString(), null, Integer.valueOf(206), null, "500-500/" + len });

        /* If-Range tests */
        // Valid
        parameterSets.add(new Object[] {
                "bytes=0-9", lastModified, Integer.valueOf(206), "10", "0-9/" + len });
        // Nonsense data (request rejected)
        parameterSets.add(new Object[] { "bytes=0-9", "a-b-c", Integer.valueOf(400), null, "" });
        parameterSets.add(new Object[] { "bytes=0-9", "W\"123\"", Integer.valueOf(400), null, "" });
        parameterSets.add(new Object[] { "bytes=0-9", "\"123\"W", Integer.valueOf(400), null, "" });
        // More than one (request rejected)
        parameterSets.add(new Object[] {
                "bytes=0-9", "\"46273648\", " + weakETag, Integer.valueOf(400), null, "" });
        // Different date (return whole entity)
        parameterSets.add(new Object[] {
                "bytes=0-9", FastHttpDateFormat.formatDate(1000), Integer.valueOf(200), strLen, "" });
        // Valid weak etag
        parameterSets.add(new Object[] {
                "bytes=0-9", weakETag, Integer.valueOf(200), strLen, "" });
        // Invalid strong etag
        parameterSets.add(new Object[] {
                "bytes=0-9", "\"46273648\"", Integer.valueOf(200), strLen, "" });
        // Valid strong etag
        parameterSets.add(new Object[] {
                "bytes=0-9", strongETag, Integer.valueOf(206), "10", "0-9/" + len });

        return parameterSets;
    }

    @Parameter(0)
    public String rangeHeader;
    @Parameter(1)
    public String ifRangeHeader;
    @Parameter(2)
    public int responseCodeExpected;
    @Parameter(3)
    public String contentLengthExpected;
    @Parameter(4)
    public String responseRangeExpected;

    @Test
    public void testRange() throws Exception {

        Tomcat tomcat = getTomcatInstance();

        File appDir = new File("test/webapp");
        Context ctxt = tomcat.addContext("", appDir.getAbsolutePath());

        Wrapper wrapper = Tomcat.addServlet(ctxt, "default", DefaultServlet.class.getName());
        if (ifRangeHeader != null && ifRangeHeader.startsWith("\"")) {
            wrapper.addInitParameter("useStrongETags", "true");
        }
        ctxt.addServletMappingDecoded("/", "default");

        tomcat.start();

        // Set up parameters
        String path = "http://localhost:" + getPort() + "/index.html";
        ByteChunk responseBody = new ByteChunk();
        Map<String,List<String>> responseHeaders = new HashMap<>();

        Map<String,List<String>> requestHeaders = buildRangeHeader(rangeHeader);
        if (ifRangeHeader != null) {
            List<String> values = new ArrayList<>(1);
            values.add(ifRangeHeader);
            requestHeaders.put("If-Range", values);
        }

        int rc = getUrl(path, responseBody, requestHeaders, responseHeaders);

        // Check the result
        Assert.assertEquals(responseCodeExpected, rc);

        if (contentLengthExpected != null && contentLengthExpected.length() > 0) {
            String contentLength = responseHeaders.get("Content-Length").get(0);
            Assert.assertEquals(contentLengthExpected, contentLength);
        }

        if (responseRangeExpected.length() > 0) {
            String responseRange = null;
            List<String> headerValues = responseHeaders.get("Content-Range");
            if (headerValues != null && headerValues.size() == 1) {
                responseRange = headerValues.get(0);
            }
            if (responseRange != null) {
                Assert.assertEquals("bytes " + responseRangeExpected, responseRange);
            } else {
                Assert.assertTrue(
                        "Expected `Content-Range: " + "bytes " + responseRangeExpected +
                                "` in multipart/byteranges response body not found!",
                        responseBody.toString().contains("bytes " + responseRangeExpected));
            }
        }
    }


    private static Map<String,List<String>> buildRangeHeader(String... headerValues) {
        Map<String,List<String>> requestHeaders = new HashMap<>();
        List<String> values = new ArrayList<>();
        for (String headerValue : headerValues) {
            if (headerValue.length() > 0) {
                values.add(headerValue);
            }
        }

        if (values.size() == 0) {
            return null;
        }

        requestHeaders.put("range", values);

        return requestHeaders;
    }
}
