Package org.apache.ace.agent.itest

Source Code of org.apache.ace.agent.itest.AgentDeploymentTest

/*
* 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.agent.itest;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.ace.agent.AgentConstants;
import org.apache.ace.agent.AgentControl;
import org.apache.ace.agent.ConfigurationHandler;
import org.apache.ace.agent.DeploymentHandler;
import org.apache.ace.agent.EventListener;
import org.apache.ace.agent.LoggingHandler.Levels;
import org.apache.ace.test.constants.TestConstants;
import org.apache.ace.test.utils.FileUtils;
import org.apache.felix.dm.Component;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.Version;
import org.osgi.service.http.HttpService;

/**
* Tests updating the management agent. In fact it tests different failure paths first, and finally gets to update the
* agent. The tests it does are:
* <ul>
* <li>Try to update to a corrupt bundle (with some random garbage injected in the JAR file).</li>
* <li>Try to update to a bundle that does not resolve because of some impossible import package statement.</li>
* <li>Try to update to a bundle that does resolve, but does not start because of a non-existing bundle activator.</li>
* <li>Update to a new version of the agent (actually, it's the same bundle, but with a different version.</li>
* </ul>
*/
public class AgentDeploymentTest extends BaseAgentTest {

    private enum Failure {
        EMPTY_STREAM, CORRUPT_STREAM, ABORT_STREAM, VERSIONS_RETRY_AFTER, DEPLOYMENT_RETRY_AFTER, CONTENT_RANGE
    }

    private static class TestAuditlogServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;

        // FIXME Ignoring auditlog.. but why do we get and empty send if we set range to high?

        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
            response.setContentType("text/plain");
            PrintWriter writer = response.getWriter();
            writer.println(request.getParameter("tid") + "," + request.getParameter("logid") + ",0-10");
            writer.close();
        }

        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
            InputStream is = request.getInputStream();
            while (is.read() != -1) {
            }
            is.close();
            response.setContentType("text/plain");
        }
    }

    private static class TestDeploymentServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;

        private static final String BACKOFF_TIME = "1";

        private final Map<String, TestPackage> m_packages = new HashMap<String, TestPackage>();
        private final String m_agentId;
        private Failure m_failure;

        public TestDeploymentServlet(String agentId) {
            m_agentId = agentId;
        }

        public synchronized void addPackage(TestPackage testPackage) {
            m_packages.put(testPackage.getVersion().toString(), testPackage);
        }

        public synchronized void reset() {
            m_failure = null;
            m_packages.clear();
        }

        public synchronized void setFailure(Failure failure) {
            m_failure = failure;
        }

        @Override
        protected synchronized void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String pathinfoTail = req.getPathInfo().replaceFirst("/" + m_agentId + "/versions/?", "");
            if (pathinfoTail.equals("")) {
                sendVersions(resp);
            }
            else {
                TestPackage dpackage = m_packages.get(pathinfoTail);
                if (dpackage == null) {
                    throw new IllegalStateException("Test error! Should never happen... " + pathinfoTail);
                }
                sendPackage(dpackage, req, resp);
            }
        }

        @Override
        protected synchronized void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String pathinfoTail = req.getPathInfo().replaceFirst("/" + m_agentId + "/versions/?", "");
            if (pathinfoTail.equals("")) {
                sendVersions(resp);
            }
            else {
                TestPackage dpackage = m_packages.get(pathinfoTail);
                if (dpackage == null) {
                    throw new IllegalStateException("Test error! Should never happen... " + pathinfoTail);
                }
                int offset = -2;
                resp.addIntHeader("X-ACE-DPSize", offset + dpackage.getVersion().getMajor());
                resp.flushBuffer();
            }
        }

        private void sendPackage(TestPackage dpackage, HttpServletRequest req, HttpServletResponse resp) throws IOException {
            if (m_failure == Failure.DEPLOYMENT_RETRY_AFTER) {
                resp.addHeader("Retry-After", BACKOFF_TIME);
                resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Simulated server overload");
                m_failure = null;
                return;
            }

            final long fileLength = dpackage.getFile().length();
            final long middle = fileLength / 2;

            long start = 0L;
            long end = fileLength;

            if (m_failure == Failure.CONTENT_RANGE) {
                String rangeHdr = req.getHeader("Range");
                if (rangeHdr != null && rangeHdr.startsWith("bytes=")) {
                    // Continuation...
                    String[] range = rangeHdr.substring(6).split("-");

                    start = Long.parseLong(range[0]);
                }
                else {
                    // Initial chuck...
                    end = fileLength / 2;
                }

                if (start == end) {
                    // Invalid...
                    resp.addHeader("Content-Range", String.format("bytes */%d", fileLength));
                    resp.setStatus(416); // content range not satisfiable...
                    return;
                }

                resp.addHeader("Content-Range", String.format("bytes %d-%d/%d", start, end - 1, fileLength));
                resp.setStatus(206); // partial
            }

            RandomAccessFile raf = null;
            OutputStream os = null;
            try {
                raf = new RandomAccessFile(dpackage.getFile(), "r");
                os = resp.getOutputStream();

                if (m_failure == Failure.EMPTY_STREAM) {
                    return;
                }

                if (m_failure == Failure.CORRUPT_STREAM) {
                    os.write("garbage".getBytes());
                }

                if (m_failure == Failure.CONTENT_RANGE) {
                    raf.seek(start);
                }

                int b;
                int count = 0;
                while (count < (end - start) && (b = raf.read()) != -1) {
                    os.write(b);
                    if (count++ == middle && m_failure == Failure.ABORT_STREAM) {
                        break;
                    }
                }
            }
            finally {
                raf.close();
                if (os != null) {
                    os.close();
                }
            }
        }

        private void sendVersions(HttpServletResponse resp) throws IOException {
            if (m_failure == Failure.VERSIONS_RETRY_AFTER) {
                resp.addHeader("Retry-After", BACKOFF_TIME);
                resp.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, "Simulated server overload");
                m_failure = null;
                return;
            }
            PrintWriter writer = resp.getWriter();
            for (String version : m_packages.keySet()) {
                writer.println(version);
            }
            writer.close();
            resp.setContentType("text/plain");
            resp.setStatus(200);
        }
    }

    private static class TestEventListener implements EventListener {
        private static boolean matches(Map<String, String> source, Map<String, String> target) {
            for (Map.Entry<String, String> sourceEntry : source.entrySet()) {
                String sourceKey = sourceEntry.getKey();
                String sourceValue = sourceEntry.getValue();

                if (!target.containsKey(sourceKey)) {
                    return false;
                }
                String targetValue = target.get(sourceKey);
                if (!sourceValue.equals(targetValue)) {
                    return false;
                }
            }

            return true;
        }

        private final Map<String, List<Map<String, String>>> m_topics = new HashMap<String, List<Map<String, String>>>();

        public boolean containsTopic(String topic) {
            synchronized (m_topics) {
                return m_topics.containsKey(topic);
            }
        }

        public boolean containsTopic(String topic, Map<String, String> expectedProperties) {
            synchronized (m_topics) {
                List<Map<String, String>> payloads = m_topics.get(topic);
                if (payloads == null || payloads.isEmpty()) {
                    return expectedProperties.isEmpty();
                }
                for (Map<String, String> payload : payloads) {
                    if (matches(expectedProperties, payload)) {
                        return true;
                    }
                }
                return false;
            }
        }

        public Map<String, List<Map<String, String>>> getTopics() {
            Map<String, List<Map<String, String>>> result;
            synchronized (m_topics) {
                result = new HashMap<String, List<Map<String, String>>>(m_topics);
            }
            return result;
        }

        @Override
        public void handle(String topic, Map<String, String> payload) {
            if (LOGLEVEL == Levels.DEBUG) {
                System.out.printf("Handling event: %s => %s.%n", topic, payload);
            }

            synchronized (m_topics) {
                List<Map<String, String>> payloads = m_topics.get(topic);
                if (payloads == null) {
                    payloads = new ArrayList<Map<String, String>>();
                    m_topics.put(topic, payloads);
                }
                payloads.add(payload);
            }
        }
    }

    private static class TestUpdateServlet extends HttpServlet {
        private static final long serialVersionUID = 1L;

        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.setContentType("text/plain");
            resp.setStatus(200);
        }
    }

    private static final String AGENT_INSTALLATION_START = "agent/defaultController/installation/START";
    private static final String AGENT_INSTALLATION_COMPLETE = "agent/defaultController/installation/COMPLETE";

    private static final String AGENT_ID = "007";
    private static final String TEST_BUNDLE_NAME_PREFIX = "test.bundle";
    private static final Levels LOGLEVEL = Levels.INFO;

    private static final Version V1_0_0 = Version.parseVersion("1.0.0");
    private static final Version V2_0_0 = Version.parseVersion("2.0.0");
    private static final Version V3_0_0 = Version.parseVersion("3.0.0");
    private static final Version V4_0_0 = Version.parseVersion("4.0.0");
    private static final Version V5_0_0 = Version.parseVersion("5.0.0");
    private static final Version V6_0_0 = Version.parseVersion("6.0.0");

    private volatile TestDeploymentServlet m_servlet;
    private volatile HttpService m_http;
    private volatile TestEventListener m_listener;

    private TestPackage m_package1;
    private TestPackage m_package2;
    private TestPackage m_package3;
    private TestPackage m_package4;
    private TestPackage m_package5;
    private TestPackage m_package6;
    private TestPackage m_package7;

    /**
     * Test case for ACE-323: when a version of a DP was downloaded correctly, but did not install correctly, we should
     * not keep trying, unless a newer version of that DP is available.
     */
    public void testFailedDeploymentWithoutRetrying() throws Exception {
        setupAgentForNonStreamingDeployment();

        expectSuccessfulDeployment(m_package1, null);

        // Try to install a DP that fails due to an aborted stream...
        expectFailedDeployment(m_package2, Failure.ABORT_STREAM);
        waitForInstalledVersion(V1_0_0);

        // The failed DP should not be installed again...
        TimeUnit.SECONDS.sleep(2); // sleep a little while to show the retry in the log...

        // If we install a newer version, it should succeed...
        expectSuccessfulDeployment(m_package6, null);

        TimeUnit.SECONDS.sleep(2); // sleep a little while to receive async events..

        // Check our event log, should contain all handled events...
        Map<String, List<Map<String, String>>> topics = m_listener.getTopics();

        List<Map<String, String>> events = topics.get(AGENT_INSTALLATION_START);
        // should contain exactly three different elements...
        assertEquals(events.toString(), 3, events.size());

        events = topics.get(AGENT_INSTALLATION_COMPLETE);
        // should contain exactly three different elements...
        assertEquals(events.toString(), 3, events.size());
    }

    /**
     * Tests that we can install upgrades for an earlier installed DP.
     */
    public void testGetSizeEstimateForDeploymentPackage() throws Exception {
        AgentControl control = getService(AgentControl.class);

        Map<String, String> props = createAgentConfiguration(false /* useStreaming */, 1000 /* secs */);

        ConfigurationHandler configurationHandler = control.getConfigurationHandler();
        configurationHandler.putAll(props);

        // Allow configuration to propagate...
        Thread.sleep(100L);

        synchronized (m_servlet) {
            m_servlet.reset();
        }

        waitForInstalledVersion(Version.emptyVersion);

        synchronized (m_servlet) {
            m_servlet.addPackage(m_package1);
            m_servlet.addPackage(m_package2);
            m_servlet.addPackage(m_package6);
        }

        DeploymentHandler deploymentHandler = control.getDeploymentHandler();
        // the size is (major-version # - 2)...
        assertEquals(4, deploymentHandler.getSize(V6_0_0, false));
        assertEquals(0, deploymentHandler.getSize(V2_0_0, false));
        assertEquals(-1, deploymentHandler.getSize(V1_0_0, false));
    }

    /**
     * Tests that we can install upgrades for an earlier installed DP.
     */
    public void testInstallUpgradeDeploymentPackage() throws Exception {
        setupAgentForNonStreamingDeployment();

        // Try to install a DP that fails at bundle-starting due to a non-existing class, but this does not revert the
        // installation of the DP itself...
        expectSuccessfulDeployment(m_package5, null);

        // If we install a newer version, it should succeed...
        expectSuccessfulDeployment(m_package6, null);
    }

    /**
     * Tests the deployment of "non-streamed" deployment packages in various situations.
     */
    public void testNonStreamingDeployment() throws Exception {
        setupAgentForNonStreamingDeployment();

        expectSuccessfulDeployment(m_package6, null);
    }

    /**
     * Tests the deployment of "non-streamed" deployment packages in various situations.
     */
    public void testNonStreamingDeployment_AbortedStream() throws Exception {
        setupAgentForNonStreamingDeployment();

        expectFailedDeployment(m_package5, Failure.ABORT_STREAM);
    }

    /**
     * Tests the deployment of "non-streamed" deployment packages in various situations.
     * <p>
     * This test simulates a DP that is already downloaded, but not yet installed as reported in ACE-413.
     * </p>
     */
    public void testNonStreamingDeployment_ChunkedContentAlreadyCompletelyDownloaded() throws Exception {
        setupAgentForNonStreamingDeployment();

        // Simulate that the DP is already downloaded...
        simulateDPDownloadComplete(m_package6);

        expectSuccessfulDeployment(m_package6, Failure.CONTENT_RANGE);
    }

    /**
     * Tests the deployment of "non-streamed" deployment packages in various situations.
     */
    public void testNonStreamingDeployment_ChunkedContentRange() throws Exception {
        setupAgentForNonStreamingDeployment();

        expectSuccessfulDeployment(m_package6, Failure.CONTENT_RANGE);
    }

    /**
     * Tests the deployment of "non-streamed" deployment packages in various situations.
     */
    public void testNonStreamingDeployment_CorruptStream() throws Exception {
        setupAgentForNonStreamingDeployment();

        expectFailedDeployment(m_package4, Failure.CORRUPT_STREAM);
    }

    /**
     * Tests the deployment of "non-streamed" deployment packages in various situations.
     */
    public void testNonStreamingDeployment_DeploymentRetryAfter() throws Exception {
        setupAgentForNonStreamingDeployment();

        expectSuccessfulDeployment(m_package2, Failure.DEPLOYMENT_RETRY_AFTER);
    }

    /**
     * Tests the deployment of "non-streamed" deployment packages in various situations.
     */
    public void testNonStreamingDeployment_EmptyStream() throws Exception {
        setupAgentForNonStreamingDeployment();

        expectFailedDeployment(m_package3, Failure.EMPTY_STREAM);
    }

    /**
     * ACE-451: Tests the deployment of an invalid "non-streamed" deployment packages, which should cause the
     * installation to be aborted.
     */
    public void testNonStreamingDeployment_InvalidDeploymentPackage() throws Exception {
        setupAgentForNonStreamingDeployment();

        expectFailedDeployment(m_package7, null);
    }

    /**
     * Tests the deployment of "non-streamed" deployment packages in various situations.
     */
    public void testNonStreamingDeployment_VersionsRetryAfter() throws Exception {
        setupAgentForNonStreamingDeployment();

        expectSuccessfulDeployment(m_package1, Failure.VERSIONS_RETRY_AFTER);
    }

    /**
     * Tests the deployment of "streamed" deployment packages in various situations.
     */
    public void testStreamingDeployment() throws Exception {
        setupAgentForStreamingDeployment();

        expectSuccessfulDeployment(m_package6, null);
    }

    /**
     * Tests the deployment of "streamed" deployment packages in various situations.
     */
    public void testStreamingDeployment_AbortStream() throws Exception {
        setupAgentForStreamingDeployment();

        expectFailedDeployment(m_package5, Failure.ABORT_STREAM);
    }

    /**
     * Tests the deployment of "streamed" deployment packages in various situations.
     */
    public void testStreamingDeployment_ChunkedContentRange() throws Exception {
        setupAgentForStreamingDeployment();

        expectSuccessfulDeployment(m_package1, Failure.CONTENT_RANGE);
    }

    /**
     * Tests the deployment of "streamed" deployment packages in various situations.
     */
    public void testStreamingDeployment_CorruptStream() throws Exception {
        setupAgentForStreamingDeployment();

        expectFailedDeployment(m_package4, Failure.CORRUPT_STREAM);
    }

    /**
     * Tests the deployment of "streamed" deployment packages in various situations.
     */
    public void testStreamingDeployment_DeploymentRetryAfter() throws Exception {
        setupAgentForStreamingDeployment();

        expectSuccessfulDeployment(m_package2, Failure.DEPLOYMENT_RETRY_AFTER);
    }

    /**
     * Tests the deployment of "streamed" deployment packages in various situations.
     */
    public void testStreamingDeployment_EmptyStream() throws Exception {
        setupAgentForStreamingDeployment();

        expectFailedDeployment(m_package3, Failure.EMPTY_STREAM);
    }

    /**
     * ACE-451: Tests the deployment of an invalid "streamed" deployment packages, which should cause the installation
     * to be aborted.
     */
    public void testStreamingDeployment_InvalidDeploymentPackage() throws Exception {
        setupAgentForStreamingDeployment();

        expectFailedDeployment(m_package7, null);
    }

    /**
     * Tests the deployment of "streamed" deployment packages in various situations.
     */
    public void testStreamingDeployment_VersionsRetryAfter() throws Exception {
        setupAgentForStreamingDeployment();

        expectSuccessfulDeployment(m_package1, Failure.VERSIONS_RETRY_AFTER);
    }

    /**
     * Tests the deployment of "streamed" deployment packages simulating an "unstable" connection.
     */
    public void testStreamingDeploymentWithUnstableConnection() throws Exception {
        setupAgentForStreamingDeployment();

        expectSuccessfulDeployment(m_package1, null);

        expectFailedDeployment(m_package6, Failure.EMPTY_STREAM);
        waitForInstalledVersion(V1_0_0);

        expectFailedDeployment(m_package6, Failure.CORRUPT_STREAM);
        waitForInstalledVersion(V1_0_0);

        expectFailedDeployment(m_package6, Failure.ABORT_STREAM);
        waitForInstalledVersion(V1_0_0);

        expectFailedDeployment(m_package6, Failure.EMPTY_STREAM);
        waitForInstalledVersion(V1_0_0);

        expectFailedDeployment(m_package6, null);
    }

    @Override
    protected void configureAdditionalServices() throws Exception {
        TestBundle bundle1v1 = new TestBundle(TEST_BUNDLE_NAME_PREFIX.concat("1"), V1_0_0);
        TestBundle bundle1v2 = new TestBundle(TEST_BUNDLE_NAME_PREFIX.concat("1"), V2_0_0);
        TestBundle bundle2v1 = new TestBundle(TEST_BUNDLE_NAME_PREFIX.concat("2"), V1_0_0);
        TestBundle bundle2v2 = new TestBundle(TEST_BUNDLE_NAME_PREFIX.concat("2"), V2_0_0);
        TestBundle bundle3v1 = new TestBundle(TEST_BUNDLE_NAME_PREFIX.concat("3"), V1_0_0, Constants.BUNDLE_ACTIVATOR, "no.such.Class");
        TestBundle bundle3v2 = new TestBundle(TEST_BUNDLE_NAME_PREFIX.concat("3"), V2_0_0);

        m_package1 = new TestPackage(AGENT_ID, V1_0_0, bundle1v1);
        m_package2 = new TestPackage(AGENT_ID, V2_0_0, bundle1v2);
        m_package3 = new TestPackage(AGENT_ID, V3_0_0, bundle1v2, bundle2v1);
        m_package4 = new TestPackage(AGENT_ID, V4_0_0, bundle1v2, bundle2v2);
        m_package5 = new TestPackage(AGENT_ID, V5_0_0, bundle1v2, bundle2v2, bundle3v1);
        m_package6 = new TestPackage(AGENT_ID, V6_0_0, bundle1v2, bundle2v2, bundle3v2);
        // This leads to an *incorrect* DP, as it contains two bundles with the same BSN...
        m_package7 = new TestPackage(AGENT_ID, V1_0_0, bundle1v1, bundle1v2);

        m_servlet = new TestDeploymentServlet(AGENT_ID);

        m_http.registerServlet("/deployment", m_servlet, null, null);
        m_http.registerServlet("/agent", new TestUpdateServlet(), null, null);
        m_http.registerServlet("/auditlog", new TestAuditlogServlet(), null, null);
    }

    @Override
    protected void doTearDown() throws Exception {
        // Remove all provisioned components...
        m_dependencyManager.clear();

        m_http.unregister("/deployment");
        m_http.unregister("/agent");
        m_http.unregister("/auditlog");

        // Force an uninstall of all remaining test bundles...
        for (Bundle bundle : m_bundleContext.getBundles()) {
            String bsn = bundle.getSymbolicName();
            if (bsn.startsWith(TEST_BUNDLE_NAME_PREFIX)) {
                bundle.uninstall();
            }
        }

        resetAgentBundleState();
    }

    @Override
    protected Component[] getDependencies() {
        m_listener = new TestEventListener();
        return new Component[] {
            createComponent()
                .setImplementation(this)
                .add(createServiceDependency().setService(HttpService.class).setRequired(true)),
            createComponent()
                .setInterface(EventListener.class.getName(), null)
                .setImplementation(m_listener)
        };
    }

    private Map<String, String> createAgentConfiguration(boolean useStreaming, int syncInterval) {
        Map<String, String> props = new HashMap<String, String>();
        props.put(AgentConstants.CONFIG_DISCOVERY_SERVERURLS, String.format("http://localhost:%d/", TestConstants.PORT));
        props.put(AgentConstants.CONFIG_IDENTIFICATION_AGENTID, AGENT_ID);
        props.put(AgentConstants.CONFIG_LOGGING_LEVEL, LOGLEVEL.name());
        props.put(AgentConstants.CONFIG_CONTROLLER_STREAMING, Boolean.toString(useStreaming));
        props.put(AgentConstants.CONFIG_CONTROLLER_SYNCDELAY, "1");
        props.put(AgentConstants.CONFIG_CONTROLLER_SYNCINTERVAL, Integer.toString(syncInterval));
        props.put(AgentConstants.CONFIG_CONTROLLER_RETRIES, "2");
        return props;
    }

    private void deployPackage(TestPackage dpackage, Failure failure) {
        synchronized (m_servlet) {
            m_servlet.setFailure(failure);
            m_servlet.addPackage(dpackage);
        }
    }

    private void expectFailedDeployment(TestPackage dpackage, Failure failure) throws Exception {
        deployPackage(dpackage, failure);

        waitForEventReceived(AGENT_INSTALLATION_START);
        waitForEventReceived(AGENT_INSTALLATION_COMPLETE, "successful", "false");
    }

    private void expectSuccessfulDeployment(TestPackage dpackage, Failure failure) throws Exception {
        deployPackage(dpackage, failure);

        waitForEventReceived(AGENT_INSTALLATION_START);
        waitForEventReceived(AGENT_INSTALLATION_COMPLETE, "successful", "true");

        waitForInstalledVersion(dpackage.getVersion());
    }

    private void setupAgentForNonStreamingDeployment() throws Exception {
        AgentControl control = getService(AgentControl.class);

        Map<String, String> props = createAgentConfiguration(false /* useStreaming */, 1 /* sec */);

        ConfigurationHandler configurationHandler = control.getConfigurationHandler();
        configurationHandler.putAll(props);

        synchronized (m_servlet) {
            m_servlet.reset();
        }

        waitForInstalledVersion(Version.emptyVersion);
    }

    private void setupAgentForStreamingDeployment() throws Exception {
        AgentControl control = getService(AgentControl.class);

        Map<String, String> props = createAgentConfiguration(true /* useStreaming */, 1 /* sec */);

        ConfigurationHandler configurationHandler = control.getConfigurationHandler();
        configurationHandler.putAll(props);

        waitForInstalledVersion(Version.emptyVersion);
    }

    /**
     * Simulates a DP that is already completely downloaded.
     *
     * @param _package
     *            the test package to simulate a download for, cannot be <code>null</code>.
     * @throws IOException
     *             in case of I/O problems.
     */
    private void simulateDPDownloadComplete(TestPackage _package) throws IOException {
        Bundle agentBundle = FrameworkUtil.getBundle(AgentConstants.class);
        assertNotNull(agentBundle);
        assertFalse(agentBundle.getBundleId() == m_bundleContext.getBundle().getBundleId());

        // The filename used for DP is the encoded URL...
        String dpFilename = String.format("http%%3A%%2F%%2Flocalhost%%3A%d%%2Fdeployment%%2F%s%%2Fversions%%2F%s", TestConstants.PORT, AGENT_ID, _package.getVersion());
        File dpFile = new File(agentBundle.getBundleContext().getDataFile(""), dpFilename);

        FileUtils.copy(_package.getFile(), dpFile);
    }

    private void waitForEventReceived(String topic) throws Exception {
        int timeout = 10000;
        while (!m_listener.containsTopic(topic)) {
            Thread.sleep(100);
            if (timeout-- <= 0) {
                fail("Timed out while waiting for event " + topic);
            }
        }
    }

    private void waitForEventReceived(String topic, String... properties) throws Exception {
        Map<String, String> props = new HashMap<String, String>();
        for (int i = 0; i < properties.length; i += 2) {
            props.put(properties[i], properties[i + 1]);
        }

        int timeout = 100;
        while (!m_listener.containsTopic(topic, props)) {
            Thread.sleep(100);
            if (timeout-- <= 0) {
                fail("Timed out while waiting for event " + topic);
            }
        }
    }

    private void waitForInstalledVersion(Version version) throws Exception {
        ServiceReference reference = m_bundleContext.getServiceReference(AgentControl.class.getName());

        try {
            AgentControl control = (AgentControl) m_bundleContext.getService(reference);
            DeploymentHandler deploymentHandler = control.getDeploymentHandler();

            int timeout = 100;
            while (!deploymentHandler.getInstalledVersion().equals(version)) {
                Thread.sleep(100);
                if (timeout-- <= 0) {
                    fail("Timed out while waiting for deployment " + version);
                }
            }
        }
        finally {
            m_bundleContext.ungetService(reference);
        }
    }
}
TOP

Related Classes of org.apache.ace.agent.itest.AgentDeploymentTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.