/*
 * 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.ace.deployment.servlet;

import static org.apache.ace.test.utils.TestUtils.UNIT;
import static org.apache.ace.test.utils.TestUtils.configureObject;
import static org.apache.ace.test.utils.TestUtils.createMockObjectAdapter;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.ace.deployment.provider.ArtifactData;
import org.apache.ace.deployment.provider.DeploymentProvider;
import org.apache.ace.deployment.streamgenerator.StreamGenerator;
import org.easymock.IAnswer;
import org.osgi.service.log.LogService;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

public class DeploymentServletTest {

    // the servlet under test
    private DeploymentServlet m_servlet;

    private long m_artifactSize;

    // request state
    private HttpServletRequest m_request;
    private String m_requestCurrentParameter;
    private String m_requestRangeHeader;
    private String m_requestPathInfo;

    // response state
    private HttpServletResponse m_response;
    private ByteArrayOutputStream m_responseOutputStream;
    private int m_responseStatus;
    private Map<String, String> m_responseHeaders;

    // deployment provider state
    private DeploymentProvider m_provider;

    // stream generator state
    private StreamGenerator m_generator;
    private String m_generatorId;
    private String m_generatorFromVersion;
    private String m_generatorToVersion;
    private InputStream m_generatorResultStream;

    @Test
    public void getDataForBadURL() throws Exception {
        HttpServletRequest garbage = createMockObjectAdapter(HttpServletRequest.class, new Object() {
            @SuppressWarnings("unused")
            public String getPathInfo() {
                return "/";
            }
        });
        m_servlet.doGet(garbage, m_response);
        assertResponseCode(HttpServletResponse.SC_BAD_REQUEST);
    }

    @Test
    public void getDataForExistingTarget() throws Exception {
        m_requestPathInfo = "/existing/versions/2.0.0";
        m_servlet.doGet(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_OK);
        assertResponseHeaderNotPresent("Content-Length");
        assertResponseOutput(0, 100);
        assertGeneratorTargetId("existing");
        assertGeneratorToVersion("2.0.0");
    }

    @Test
    public void getDataForNonExistingTarget() throws Exception {
        m_requestPathInfo = "/nonexisting/versions/2.0.0";
        m_servlet.doGet(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_NOT_FOUND);
    }

    @Test(groups = { UNIT })
    public void getDowngradeFixPackageWithNonExistingToVersion() throws Exception {
        // try to request a version range with a non-existing from-version, should cause a complete (non-fix) package to
        // be returned...
        m_requestPathInfo = "/existing/versions/1.0.0";
        m_requestCurrentParameter = "2.0.0";
        m_servlet.doGet(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_NOT_FOUND);
    }

    @Test
    public void getRangeDataForExistingTarget_badHeaderValue() throws Exception {
        // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16
        // If the server ignores a byte-range-spec because it is syntactically invalid, the server SHOULD treat the
        // request as if the invalid Range header field did not exist. (Normally, this means return a 200 response
        // containing the full entity).
        m_requestPathInfo = "/existing/versions/2.0.0";
        m_requestRangeHeader = "bytes=a-1";
        m_servlet.doGet(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_OK);
        assertResponseHeaderNotPresent("Content-Length");
        assertResponseOutput(0, 100);
    }

    @Test
    public void getRangeDataForExistingTarget_first0lastOK() throws Exception {
        // valid range starting at 0
        m_requestPathInfo = "/existing/versions/2.0.0";
        m_requestRangeHeader = "bytes=0-10";
        m_servlet.doGet(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_PARTIAL_CONTENT);
        assertResponseHeaderNotPresent("Content-Length");
        assertResponseHeaderValue("Content-Range", "bytes 0-10/*");
    }

    @Test
    public void getRangeDataForExistingTarget_firstOKlastANY() throws Exception {
        // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1
        // If the last-byte-pos value is absent, or if the value is greater than or equal to the current length of the
        // entity-body, last-byte-pos is taken to be equal to one less than the current length of the entity- body in
        // bytes.
        m_requestPathInfo = "/existing/versions/2.0.0";
        m_requestRangeHeader = "bytes=2-";
        m_servlet.doGet(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_PARTIAL_CONTENT);
        assertResponseHeaderNotPresent("Content-Length");
        assertResponseHeaderValue("Content-Range", "bytes 2-/*");
        assertResponseOutput(2, 98);
    }

    @Test(groups = { UNIT })
    public void getRangeDataForExistingTarget_firstOKlastOK() throws Exception {
        // valid range not starting at 0
        m_requestPathInfo = "/existing/versions/2.0.0";
        m_requestRangeHeader = "bytes=2-50";
        m_servlet.doGet(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_PARTIAL_CONTENT);
        assertResponseHeaderNotPresent("Content-Length");
        assertResponseHeaderValue("Content-Range", "bytes 2-50/*");
        assertResponseOutput(2, 49);
    }

    @Test
    public void getRangeDataForExistingTarget_firstOKlastOK2() throws Exception {
        // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1
        // If the last-byte-pos value is absent, or if the value is greater than or equal to the current length of the
        // entity-body, last-byte-pos is taken to be equal to one less than the current length of the entity- body in
        // bytes.
        m_requestPathInfo = "/existing/versions/2.0.0";
        m_requestRangeHeader = "bytes=2-99";
        m_servlet.doGet(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_PARTIAL_CONTENT);
        assertResponseHeaderNotPresent("Content-Length");
        assertResponseHeaderValue("Content-Range", "bytes 2-99/*");
        assertResponseOutput(2, 98);
    }

    @Test
    public void getRangeDataForExistingTarget_firstOKlastTooBig() throws Exception {
        // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1
        // If the last-byte-pos value is absent, or if the value is greater than or equal to the current length of the
        // entity-body, last-byte-pos is taken to be equal to one less than the current length of the entity- body in
        // bytes.
        m_requestPathInfo = "/existing/versions/2.0.0";
        m_requestRangeHeader = "bytes=2-100";
        m_servlet.doGet(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_PARTIAL_CONTENT);
        assertResponseHeaderNotPresent("Content-Length");
        assertResponseHeaderValue("Content-Range", "bytes 2-100/*");
        assertResponseOutput(2, 98);
    }

    @Test
    public void getRangeDataForExistingTarget_firstOKlastTooSmall() throws Exception {
        // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1
        // If the last-byte-pos value is present, it MUST be greater than or equal to the first-byte-pos in that
        // byte-range-spec, or the byte- range-spec is syntactically invalid.

        // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16
        // If the server ignores a byte-range-spec because it is syntactically invalid, the server SHOULD treat the
        // request as if the invalid Range header field did not exist. (Normally, this means return a 200 response
        // containing the full entity).
        m_requestPathInfo = "/existing/versions/2.0.0";
        m_requestRangeHeader = "bytes=2-1";
        m_servlet.doGet(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_OK);
        assertResponseHeaderNotPresent("Content-Length");
        assertResponseOutput(0, 100);
    }

    @Test
    public void getRangeDataForExistingTarget_firstTooBiglastTooBig() throws Exception {
        // invalid range: start=toobig end=toobig
        m_requestPathInfo = "/existing/versions/2.0.0";
        m_requestRangeHeader = "bytes=100-110";
        m_servlet.doGet(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_PARTIAL_CONTENT);
        assertResponseHeaderValue("Content-Range", "bytes 100-110/*");
        assertResponseHeaderNotPresent("Content-Length");
        assertResponseOutput(-1, 0);
    }

    @Test
    public void getSizeForExistingTargetWithKnownSize() throws Exception {
        m_artifactSize = 10;
        m_requestPathInfo = "/existing/versions/2.0.0";
        m_servlet.doHead(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_OK);
        assertResponseHeaderValue("X-ACE-DPSize", "11"); // 10 + 10%
    }

    @Test
    public void getSizeForExistingTargetWithUnknownSize() throws Exception {
        m_artifactSize = -1;
        m_requestPathInfo = "/existing/versions/2.0.0";
        m_servlet.doHead(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_OK);
        assertResponseHeaderNotPresent("X-ACE-DPSize");
    }

    @Test
    public void getSizeForFixPackageExistingTargetWithKnownSize() throws Exception {
        m_artifactSize = 10;
        m_requestCurrentParameter = "2.0.0";
        m_requestPathInfo = "/existing/versions/2.0.0";
        m_servlet.doHead(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_OK);
        assertResponseHeaderValue("X-ACE-DPSize", "22"); // 20 + 10%
    }

    @Test
    public void getSizeForNonExistingTarget() throws Exception {
        m_artifactSize = 10;

        m_requestPathInfo = "/existing/versions/1.0.0";
        m_servlet.doHead(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_OK);
        assertResponseHeaderNotPresent("X-ACE-DPSize");
    }

    @Test(groups = { UNIT })
    public void getUpgradeFixPackageWithExistingFromVersion() throws Exception {
        // try to request a version range with an existing from-version, should cause a fix package to be returned...
        m_requestPathInfo = "/existing/versions/2.0.0";
        m_requestCurrentParameter = "2.0.0";
        m_servlet.doGet(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_OK);
        assertResponseOutput(0, 100);
        assertGeneratorTargetId("existing");
        assertGeneratorToVersion("2.0.0");
        assertGeneratorFromVersion("2.0.0");
    }

    @Test(groups = { UNIT })
    public void getUpgradeFixPackageWithNonExistingFromVersion() throws Exception {
        // try to request a version range with a non-existing from-version, should cause a complete (non-fix) package to
        // be returned...
        m_requestPathInfo = "/existing/versions/2.0.0";
        m_requestCurrentParameter = "1.0.0";
        m_servlet.doGet(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_OK);
        assertResponseOutput(0, 100);
        assertGeneratorTargetId("existing");
        assertGeneratorToVersion("2.0.0");
        assertGeneratorFromVersion(null);
    }

    @Test(groups = { UNIT })
    public void getUpgradeFixPackageWithNonExistingToVersion() throws Exception {
        // try to request a version range with a non-existing from-version, should cause a complete (non-fix) package to
        // be returned...
        m_requestPathInfo = "/existing/versions/3.0.0";
        m_requestCurrentParameter = "2.0.0";
        m_servlet.doGet(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_NOT_FOUND);
    }

    @Test(groups = { UNIT })
    public void getUpgradeWithExistingToVersion() throws Exception {
        // try to request a version range with a non-existing from-version, should cause a complete (non-fix) package to
        // be returned...
        m_requestPathInfo = "/existing/versions/2.0.0";
        m_requestCurrentParameter = null;
        m_servlet.doGet(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_OK);
        assertResponseOutput(0, 100);
        assertGeneratorTargetId("existing");
        assertGeneratorToVersion("2.0.0");
        assertGeneratorFromVersion(null);
    }

    @Test(groups = { UNIT })
    public void getUpgradeWithNonExistingToVersion() throws Exception {
        // try to request a version range with a non-existing from-version, should cause a complete (non-fix) package to
        // be returned...
        m_requestPathInfo = "/existing/versions/3.0.0";
        m_requestCurrentParameter = null;
        m_servlet.doGet(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_NOT_FOUND);
    }

    @Test
    public void getVersionsExistingTarget() throws Exception {
        m_requestPathInfo = "/existing/versions";
        m_servlet.doGet(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_OK);
        assertEquals(m_responseOutputStream.toString(), "2.0.0\n", "Expected to get version 2.0.0 in the response");
    }

    @Test
    public void getVersionsNonExistingTarget() throws Exception {
        m_requestPathInfo = "/nonexisting/versions";
        m_servlet.doGet(m_request, m_response);
        assertResponseCode(HttpServletResponse.SC_NOT_FOUND);
        assertResponseOutput(-1, 0);
    }

    @BeforeMethod(alwaysRun = true)
    protected void setUp() throws Exception {
        final Map<String, List<String>> providerVersions = new HashMap<>();
        providerVersions.put("existing", Arrays.asList("2.0.0"));

        final ArtifactData artifactData = createMock(ArtifactData.class);
        expect(artifactData.getSize()).andAnswer(new IAnswer<Long>() {
            @Override
            public Long answer() throws Throwable {
                return DeploymentServletTest.this.m_artifactSize;
            }
        }).anyTimes();
        replay(artifactData);

        m_provider = new DeploymentProvider() {
            public List<ArtifactData> getBundleData(String targetId, String version) throws IllegalArgumentException {
                List<String> versions = providerVersions.get(targetId);
                if (versions != null && versions.contains(version)) {
                    return Arrays.asList(artifactData);
                }
                return Collections.emptyList();
            }

            public List<ArtifactData> getBundleData(String targetId, String versionFrom, String versionTo) throws IllegalArgumentException {
                List<String> versions = providerVersions.get(targetId);
                if (versions != null && versions.contains(versionFrom) && versions.contains(versionTo)) {
                    return Arrays.asList(artifactData, artifactData);
                }
                return Collections.emptyList();
            }

            public List<String> getVersions(String targetId) throws IllegalArgumentException {
                if (providerVersions.containsKey(targetId)) {
                    return providerVersions.get(targetId);
                }
                throw new IllegalArgumentException();
            }
        };

        m_generator = new StreamGenerator() {
            public InputStream getDeploymentPackage(String id, String version) throws IOException {
                if (m_generatorResultStream == null) {
                    throw new IOException("No data for " + id + " " + version);
                }
                m_generatorId = id;
                m_generatorToVersion = version;
                return m_generatorResultStream;
            }

            public InputStream getDeploymentPackage(String id, String fromVersion, String toVersion) throws IOException {
                if (m_generatorResultStream == null) {
                    throw new IOException("No delta for " + id + " " + fromVersion + " " + toVersion);
                }
                m_generatorId = id;
                m_generatorFromVersion = fromVersion;
                m_generatorToVersion = toVersion;
                return m_generatorResultStream;
            }
        };

        // create a HttpServletRequest mock object
        m_request = createMockObjectAdapter(HttpServletRequest.class, new Object() {
            @SuppressWarnings("unused")
            public String getHeader(String name) {
                if (name.equals("Range")) {
                    return m_requestRangeHeader;
                }
                return null;
            }

            @SuppressWarnings("unused")
            public String getParameter(String param) {
                if (param.equals(DeploymentServlet.CURRENT)) {
                    return m_requestCurrentParameter;
                }
                return null;
            }

            @SuppressWarnings("unused")
            public String getPathInfo() {
                return m_requestPathInfo;
            }
        });

        // create a HttpServletResponse mock object
        m_response = createMockObjectAdapter(HttpServletResponse.class, new Object() {
            @SuppressWarnings("unused")
            public void addHeader(String name, String value) {
                m_responseHeaders.put(name, value);
            }

            @SuppressWarnings("unused")
            public ServletOutputStream getOutputStream() {
                return new ServletOutputStream() {
                    @Override
                    public void write(int b) throws IOException {
                        m_responseOutputStream.write(b);
                    }

                    @Override
                    public boolean isReady() {
                        return true;
                    }

                    @Override
                    public void setWriteListener(WriteListener l) {
                        // nop
                    }
                };
            }

            public synchronized void sendError(int status) {
                m_responseStatus = status;
            }

            @SuppressWarnings("unused")
            public void sendError(int status, String desc) {
                sendError(status);
            }

            @SuppressWarnings("unused")
            public void setHeader(String name, String value) {
                m_responseHeaders.put(name, value);
            }

            public void setStatus(int status) {
                m_responseStatus = status;
            }

            @SuppressWarnings("unused")
            public void setStatus(int status, String desc) {
                setStatus(status);
            }
        });

        // create the instance to test
        m_servlet = new DeploymentServlet();
        configureObject(m_servlet, LogService.class);
        configureObject(m_servlet, StreamGenerator.class, m_generator);
        configureObject(m_servlet, DeploymentProvider.class, m_provider);

        byte[] data = new byte[100];
        for (int i = 0; i < data.length; i++) {
            data[i] = (byte) (i + 1);
        }

        // set the default state
        m_generatorResultStream = new ByteArrayInputStream(data);
        m_requestCurrentParameter = null;
        m_generatorId = null;
        m_generatorFromVersion = null;
        m_generatorToVersion = null;

        m_responseStatus = HttpServletResponse.SC_OK;
        m_responseHeaders = new HashMap<>();
        m_requestRangeHeader = null;
        m_responseOutputStream = new ByteArrayOutputStream();
    }

    private void assertGeneratorFromVersion(String version) {
        assertEquals(m_generatorFromVersion, version, "Wrong from-version");
    }

    private void assertGeneratorTargetId(String id) {
        assertEquals(m_generatorId, id, "Wrong target ID");
    }

    private void assertGeneratorToVersion(String version) {
        assertEquals(m_generatorToVersion, version, "Wrong to-version");
    }

    private void assertResponseCode(int value) throws Exception {
        assertEquals(m_responseStatus, value, "Incorrect response code from server");
    }

    private void assertResponseHeaderNotPresent(String name) throws Exception {
        assertFalse(m_responseHeaders.containsKey(name), "Expected response " + name + " header to NOT be set");
    }

    private void assertResponseHeaderValue(String name, String value) throws Exception {
        assertTrue(m_responseHeaders.containsKey(name), "Expected response " + name + " header to be set");
        assertEquals(m_responseHeaders.get(name), value, "Unexpected response header");
    }

    private void assertResponseOutput(int offset, int size) throws Exception {
        byte[] data = m_responseOutputStream.toByteArray();
        assertEquals(data.length, size, "We should have got a (dummy) deployment package of");
        for (int i = 0; i < data.length; i++) {
            assertEquals(data[i], i + offset + 1);
        }
    }
}
