ace-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ma...@apache.org
Subject svn commit: r1464402 [4/11] - in /ace/trunk: org.apache.ace.deployment.api/ org.apache.ace.deployment.deploymentadmin/ org.apache.ace.deployment.itest/ org.apache.ace.deployment.itest/src/org/apache/ace/it/deployment/ org.apache.ace.deployment.provider...
Date Thu, 04 Apr 2013 09:43:37 GMT
Added: ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/provider/repositorybased/RepositoryBasedProviderPerformanceTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/provider/repositorybased/RepositoryBasedProviderPerformanceTest.java?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/provider/repositorybased/RepositoryBasedProviderPerformanceTest.java (added)
+++ ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/provider/repositorybased/RepositoryBasedProviderPerformanceTest.java Thu Apr  4 09:43:34 2013
@@ -0,0 +1,236 @@
+/*
+ * 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.provider.repositorybased;
+
+import static org.apache.ace.test.utils.TestUtils.*;
+
+import java.io.StringWriter;
+import java.util.Collection;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.ace.deployment.provider.ArtifactData;
+import org.apache.ace.repository.Repository;
+import org.apache.ace.test.utils.TestUtils;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.service.log.LogService;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+public class RepositoryBasedProviderPerformanceTest {
+
+    private static final String TAGS_TAG = "tags";
+    private static final String VERSION_TAG = "version";
+    private static final String TARGETID_TAG = "targetID";
+    private static final String ARTIFACTS_TAG = "artifacts";
+    private static final String ARTIFACT_TAG = "deploymentArtifact";
+    private static final String URL_TAG = "url";
+    private static final String DIRECTIVES_TAG = "directives";
+    private static final String ATTRIBUTES_TAG = "attributes";
+    private static final String DEPLOYMENTVERSION_TAG = "deploymentversion";
+
+    private static final String TARGET = "target";
+    private static final String RESOURCETARGET = "resource-target";
+    public static final String KEY_SYMBOLICNAME = Constants.BUNDLE_SYMBOLICNAME;
+    public static final String KEY_NAME = Constants.BUNDLE_NAME;
+    public static final String KEY_VERSION = Constants.BUNDLE_VERSION;
+    public static final String KEY_VENDOR = Constants.BUNDLE_VENDOR;
+    public static final String KEY_RESOURCE_PROCESSOR_PID = "Deployment-ProvidesResourceProcessor";
+    /**
+     * Key, intended to be used for artifacts which are bundles and will publish
+     * a resource processor (see OSGi compendium section 114.10).
+     */
+    public static final String DIRECTIVE_ISCUSTOMIZER = "DeploymentPackage-Customizer";
+
+    /**
+     * Key, intended to be used for resources which require a resource processor
+     * (see OSGi compendium section 114.10).
+     */
+    public static final String DIRECTIVE_KEY_PROCESSORID = "Resource-Processor";
+
+    /**
+     * Key, intended to be used for artifacts which have a resourceID that's different
+     * from their generated name (based on URL).
+     */
+    public static final String DIRECTIVE_KEY_RESOURCE_ID = "Resource-ID";
+
+    /**
+     * Key, intended to be used for matching processed (see ArtifactPreprocessor) to their
+     * 'original' one.
+     */
+    public static final String DIRECTIVE_KEY_BASEURL = "Base-Url";
+
+	public static final String REPOSITORY_PATH = "ACE-RepositoryPath";
+
+    public static final String MIMETYPE = "application/vnd.osgi.bundle";
+
+    private RepositoryBasedProvider m_backend;
+
+    /**
+     * Sets up for the test cases.
+     */
+    @BeforeMethod(alwaysRun = true)
+    public void setUp() throws Exception {
+        // setup mock repository
+        String range = "1-100000";
+        Repository mock = new MockDeploymentRepository(range, generateHugeTestXml());
+        m_backend = new RepositoryBasedProvider();
+        TestUtils.configureObject(m_backend, Repository.class, mock);
+        TestUtils.configureObject(m_backend, LogService.class);
+    }
+    
+    /**
+     * Test the getBundleData for a single version, returning a single bundle, for a huge XML.
+     */
+    @Test(groups = { PERFORMANCE }, timeOut = 2000 /* millis */)
+    public void testSingleBundleSingleVersionBundleDataFromHugeXml() throws Exception {
+        // will parse the entire XML structure;
+        // with XPath queries, it takes about 115 seconds of time;
+        // with a SAX parser, it takes about 0.9(!) seconds of time.
+        Collection<ArtifactData> bundleData = m_backend.getBundleData(TARGET, "44.0.0");
+        assert bundleData.size() == 1 : "Expected one bundle to be found, but found " + bundleData.size();
+    }
+
+    /**
+     * Test the getBundleData for a single version, returning a single bundle, for a huge XML.
+     */
+    @Test(groups = { PERFORMANCE }, timeOut = 3000 /* millis */)
+    public void testSingleBundleMultipleVersionBundleDataFromHugeXml() throws Exception {
+        // will parse the entire XML structure;
+        // with XPath queries, it takes about 115 seconds of time;
+        // with a SAX parser, it takes about 0.9(!) seconds of time.
+        Collection<ArtifactData> bundleData = m_backend.getBundleData(TARGET, "40.0.0", "44.6.0");
+        assert bundleData.size() == 1 : "Expected one bundle to be found, but found " + bundleData.size();
+    }
+
+    /**
+     * @return a "huge" XML repository, with lots of deployment versions (approx. 10000) for a single target.
+     */
+    private String generateHugeTestXml() throws Exception {
+        DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
+        DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
+        Document doc = docBuilder.newDocument();
+
+        // create the root element
+        Element root = doc.createElement("repository");
+        doc.appendChild(root);
+
+        // create the versions element
+        Element versions = doc.createElement("deploymentversions");
+        root.appendChild(versions);
+
+        String bundleUrl = "file:///path/to/bundle1";
+        String symName = "my-test-bundle1";
+
+        // create deployment versions
+        for (int i = 0; i < 10000; i++) {
+            Version dpVersion = new Version(i / 100, i % 100, 0);
+            Version bundleVersion = new Version(i / 100, i % 100, 1);
+            versions.appendChild(generateDeploymentVersion(doc, TARGET, dpVersion.toString(),
+                new String[] { bundleUrl, KEY_SYMBOLICNAME, symName, KEY_VERSION,
+                    bundleVersion.toString() }));
+        }
+
+        String rpUrl = "file:///path/to/rp";
+        String artUrl = "file:///path/to/artifact";
+        String rpSymName = "my-test-rp1";
+
+        versions.appendChild(generateDeploymentVersion(doc, RESOURCETARGET, "1.0.0",
+            new String[] { bundleUrl, KEY_SYMBOLICNAME, symName, KEY_VERSION, "1.0.1" },
+            new String[] { rpUrl, DIRECTIVE_ISCUSTOMIZER, "true", KEY_SYMBOLICNAME, rpSymName, KEY_VERSION, "1.0.2" },
+            new String[] { artUrl, DIRECTIVE_KEY_PROCESSORID, "my.processor.pid" },
+            new String[] { artUrl, DIRECTIVE_KEY_RESOURCE_ID, "Artifact2", DIRECTIVE_KEY_PROCESSORID, "my.processor.pid" }));
+
+        // transform the document to string
+        TransformerFactory tFactory = TransformerFactory.newInstance();
+        Transformer transformer = tFactory.newTransformer();
+        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+        transformer.setOutputProperty(OutputKeys.INDENT, "no");
+        DOMSource source = new DOMSource(doc);
+
+        StringWriter sw = new StringWriter();
+        StreamResult result = new StreamResult(sw);
+        transformer.transform(source, result);
+
+        return sw.toString();
+    }
+
+    /**
+     * Helper method to create the description of a deploymentpacakge with given data.
+     * 
+     * @param doc The document to add the version to.
+     * @param targetText The targetId in the deploymentversion.
+     * @param versionText The version in the deploymentversion.
+     * @param data An array of data for the deployment artifact. [0] is the url, and each following item is
+     *        first a directive key, and a directive value. For example,<br>
+     *        <code>new String[] { "http://mybundle", "somedirective", "somevalue" }</code>
+     * @return
+     */
+    private Node generateDeploymentVersion(Document doc, String targetText, String versionText, String[]... data) {
+        Element deploymentversion = doc.createElement(DEPLOYMENTVERSION_TAG);
+        Element attr = doc.createElement(ATTRIBUTES_TAG);
+        deploymentversion.appendChild(attr);
+
+        // Create and add targetId Tag
+        Element elem = null;
+        elem = doc.createElement(TARGETID_TAG);
+        elem.setTextContent(targetText);
+        attr.appendChild(elem);
+
+        // Create and add versionTag
+        elem = doc.createElement(VERSION_TAG);
+        elem.setTextContent(versionText);
+        attr.appendChild(elem);
+
+        // Create and add empty tagsTag to deploymentversion
+        elem = doc.createElement(TAGS_TAG);
+        deploymentversion.appendChild(elem);
+
+        // create and add bundlesTag
+        elem = doc.createElement(ARTIFACTS_TAG);
+        for (String[] s : data) {
+            Element artifact = doc.createElement(ARTIFACT_TAG);
+            Element url = doc.createElement(URL_TAG);
+            url.setTextContent(s[0]);
+            artifact.appendChild(url);
+            Element directives = doc.createElement(DIRECTIVES_TAG);
+            for (int i = 1; i < s.length; i += 2) {
+                Element directive = doc.createElement(s[i]);
+                directive.setTextContent(s[i + 1]);
+                directives.appendChild(directive);
+            }
+            artifact.appendChild(directives);
+            elem.appendChild(artifact);
+        }
+
+        deploymentversion.appendChild(elem);
+
+        return deploymentversion;
+    }
+}

Added: ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/provider/repositorybased/RepositoryBasedProviderTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/provider/repositorybased/RepositoryBasedProviderTest.java?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/provider/repositorybased/RepositoryBasedProviderTest.java (added)
+++ ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/provider/repositorybased/RepositoryBasedProviderTest.java Thu Apr  4 09:43:34 2013
@@ -0,0 +1,705 @@
+/*
+ * 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.provider.repositorybased;
+
+import static org.apache.ace.test.utils.TestUtils.UNIT;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.Attributes;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.ace.deployment.provider.ArtifactData;
+import org.apache.ace.deployment.provider.impl.ArtifactDataImpl;
+import org.apache.ace.deployment.util.test.BundleStreamGenerator;
+import org.apache.ace.repository.Repository;
+import org.apache.ace.test.utils.FileUtils;
+import org.apache.ace.test.utils.TestUtils;
+import org.osgi.framework.Constants;
+import org.osgi.service.log.LogService;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+/**
+ * This test class tests the Repositorybased Provider class.
+ * This class implements 2 backend interfaces,
+ * and both are tested here.
+ */
+public class RepositoryBasedProviderTest {
+
+    private static final String TAGS_TAG = "tags";
+    private static final String VERSION_TAG = "version";
+    private static final String TARGETID_TAG = "targetID";
+    private static final String ARTIFACTS_TAG = "artifacts";
+    private static final String ARTIFACT_TAG = "deploymentArtifact";
+    private static final String URL_TAG = "url";
+    private static final String DIRECTIVES_TAG = "directives";
+    private static final String ATTRIBUTES_TAG = "attributes";
+    private static final String DEPLOYMENTVERSION_TAG = "deploymentversion";
+    public static final String KEY_SYMBOLICNAME = Constants.BUNDLE_SYMBOLICNAME;
+    public static final String KEY_NAME = Constants.BUNDLE_NAME;
+    public static final String KEY_VERSION = Constants.BUNDLE_VERSION;
+    public static final String KEY_VENDOR = Constants.BUNDLE_VENDOR;
+    public static final String KEY_RESOURCE_PROCESSOR_PID = "Deployment-ProvidesResourceProcessor";
+    /**
+     * Key, intended to be used for artifacts which are bundles and will publish
+     * a resource processor (see OSGi compendium section 114.10).
+     */
+    public static final String DIRECTIVE_ISCUSTOMIZER = "DeploymentPackage-Customizer";
+
+    /**
+     * Key, intended to be used for resources which require a resource processor
+     * (see OSGi compendium section 114.10).
+     */
+    public static final String DIRECTIVE_KEY_PROCESSORID = "Resource-Processor";
+
+    /**
+     * Key, intended to be used for artifacts which have a resourceID that's different
+     * from their generated name (based on URL).
+     */
+    public static final String DIRECTIVE_KEY_RESOURCE_ID = "Resource-ID";
+
+    /**
+     * Key, intended to be used for matching processed (see ArtifactPreprocessor) to their
+     * 'original' one.
+     */
+    public static final String DIRECTIVE_KEY_BASEURL = "Base-Url";
+
+	public static final String REPOSITORY_PATH = "ACE-RepositoryPath";
+
+    private RepositoryBasedProvider m_backend;
+
+    private File m_tempDirectory;
+
+    private final String VERSION1 = "1.0.0";
+    private final String VERSION2 = "2.0.0";
+    private final String VERSION3 = "3.0.0";
+    private final String VERSION4 = "4.0.0";
+    private final String INVALIDVERSION = "Invalid.version.directory";
+
+    private final String TARGET = "target";
+    private final String MULTIPLEVERSIONTARGET = "multi-version-target";
+    private final String INVALIDVERSIONTARGET = "illegal-version-target";
+    private final String EMPTYVERSIONTARGET = "empty-version-target";
+    private final String RESOURCETARGET = "resource-target";
+
+    private ArtifactData BUNDLE1;
+    private ArtifactData BUNDLE3;
+    private ArtifactData BUNDLE4;
+    private ArtifactData BUNDLE4_1;
+    private ArtifactData BUNDLE5;
+    private ArtifactData BUNDLE3_2;
+    private ArtifactData BUNDLE4_2;
+
+    private ArtifactData RESOURCEPROCESSOR1;
+    private ArtifactData ARTIFACT1;
+    private ArtifactData ARTIFACT2;
+
+    @BeforeMethod(alwaysRun = true)
+    protected void setUp() throws Exception {
+
+        // first create a file
+        m_tempDirectory = FileUtils.createTempFile(null);
+        // and make a directory with that name.
+        m_tempDirectory.mkdir();
+
+        // generate sample data
+        setupSampleData();
+        String deploymentRepositoryXml = generateValidTestXml();
+        String range = "1,2,3";
+
+        // setup mock repository
+        Repository mock = new MockDeploymentRepository(range, deploymentRepositoryXml);
+        m_backend = new RepositoryBasedProvider();
+        TestUtils.configureObject(m_backend, Repository.class, mock);
+        TestUtils.configureObject(m_backend, LogService.class);
+    }
+
+    /**
+     * make a bundle with the given symbolic name and version in the given file.
+     */
+    private ArtifactData generateBundle(File file, Map<String, String> directives, String symbolicName, String version,
+        Map<String, String> additionalHeaders) throws Exception {
+        ArtifactData bundle = new ArtifactDataImpl(file.toURI().toURL(), directives, symbolicName, version, false);
+        if (additionalHeaders == null) {
+            BundleStreamGenerator.generateBundle(bundle);
+        }
+        else {
+            BundleStreamGenerator.generateBundle(bundle, additionalHeaders);
+        }
+        return bundle;
+    }
+
+    /**
+     * Create the testbundles in the tempdirectory
+     */
+    private void setupSampleData() throws Exception {
+        BUNDLE1 = generateBundle(FileUtils.createTempFile(m_tempDirectory), null, "Bundle1", "1.0.0", null);
+        BUNDLE3 = generateBundle(FileUtils.createTempFile(m_tempDirectory), null, "Bundle3", "3.0.0", null);
+        BUNDLE4 = generateBundle(FileUtils.createTempFile(m_tempDirectory), null, "Bundle4", "4.0.0", null);
+        BUNDLE4_1 = generateBundle(FileUtils.createTempFile(m_tempDirectory), null, "Bundle4", "4.1.0", null);
+        BUNDLE5 = generateBundle(FileUtils.createTempFile(m_tempDirectory), null, "Bundle5", "5.0.0", null);
+        BUNDLE3_2 = generateBundle(FileUtils.createTempFile(m_tempDirectory), null, "Bundle3", "3.0.0", null);
+        BUNDLE4_2 = generateBundle(FileUtils.createTempFile(m_tempDirectory), null, "Bundle4", "5.0.0", null);
+
+        Map<String, String> attr = new HashMap<String, String>();
+        attr.put(DIRECTIVE_ISCUSTOMIZER, "true");
+        RESOURCEPROCESSOR1 = generateBundle(FileUtils.createTempFile(m_tempDirectory), attr, "Autoconf", "1.0.0", null);
+        attr = new HashMap<String, String>();
+        attr.put(DIRECTIVE_KEY_PROCESSORID, "my.processor.pid");
+        ARTIFACT1 = new ArtifactDataImpl(FileUtils.createTempFile(m_tempDirectory).toURI().toURL(), attr, false);
+        attr = new HashMap<String, String>();
+        attr.put(DIRECTIVE_KEY_PROCESSORID, "my.processor.pid");
+        attr.put(DIRECTIVE_KEY_RESOURCE_ID, "Artifact2");
+        ARTIFACT2 = new ArtifactDataImpl(FileUtils.createTempFile(m_tempDirectory).toURI().toURL(), attr, false);
+    }
+
+    private String generateValidTestXml() {
+        Document doc = null;
+        try {
+            DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
+            DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
+            doc = docBuilder.newDocument();
+        }
+        catch (ParserConfigurationException e) {
+            // Should not happen
+            e.printStackTrace();
+        }
+
+        // create the root element
+        Element root = doc.createElement("repository");
+        doc.appendChild(root);
+
+        // create the versions element
+        Element versions = doc.createElement("deploymentversions");
+        root.appendChild(versions);
+
+        // create deployment versions
+        versions.appendChild(generateDeploymentVersion(doc, TARGET, VERSION1, new String[] {
+            BUNDLE1.getUrl().toString(), KEY_SYMBOLICNAME, BUNDLE1.getSymbolicName(),
+            KEY_VERSION, BUNDLE1.getVersion() }));
+        versions
+            .appendChild(generateDeploymentVersion(doc, MULTIPLEVERSIONTARGET, VERSION1, new String[] {
+                BUNDLE3.getUrl().toString(), KEY_SYMBOLICNAME, BUNDLE3.getSymbolicName(),
+                KEY_VERSION, BUNDLE3.getVersion() },
+                new String[] { BUNDLE4.getUrl().toString(), KEY_SYMBOLICNAME, BUNDLE4.getSymbolicName(),
+                    KEY_VERSION, BUNDLE4.getVersion() }));
+        versions
+            .appendChild(generateDeploymentVersion(doc, MULTIPLEVERSIONTARGET, VERSION2, new String[] {
+                BUNDLE4_1.getUrl().toString(), KEY_SYMBOLICNAME, BUNDLE4_1.getSymbolicName(),
+                KEY_VERSION, BUNDLE4_1.getVersion() },
+                new String[] { BUNDLE5.getUrl().toString(), KEY_SYMBOLICNAME, BUNDLE5.getSymbolicName(),
+                    KEY_VERSION, BUNDLE5.getVersion() }));
+        versions.appendChild(generateDeploymentVersion(doc, MULTIPLEVERSIONTARGET, VERSION3, new String[] {
+            BUNDLE4.getUrl().toString(), KEY_SYMBOLICNAME, BUNDLE4.getSymbolicName(),
+            KEY_VERSION, BUNDLE4.getVersion() }));
+        versions.appendChild(generateDeploymentVersion(doc, MULTIPLEVERSIONTARGET, VERSION4, new String[] {
+            BUNDLE3_2.getUrl().toString(), KEY_SYMBOLICNAME, BUNDLE3_2.getSymbolicName(),
+            KEY_VERSION, BUNDLE3_2.getVersion() },
+            new String[] { BUNDLE4_2.getUrl().toString(), KEY_SYMBOLICNAME, BUNDLE4_2.getSymbolicName(),
+                KEY_VERSION, BUNDLE4_2.getVersion() }));
+        // Add versions with special characters like ' " < >
+        versions
+            .appendChild(generateDeploymentVersion(doc, "'", VERSION1,
+                new String[] { BUNDLE1.getUrl().toString(), KEY_SYMBOLICNAME, BUNDLE1.getSymbolicName(),
+                    KEY_VERSION, BUNDLE1.getVersion() }));
+        versions
+            .appendChild(generateDeploymentVersion(doc, "\"", VERSION2,
+                new String[] { BUNDLE1.getUrl().toString(), KEY_SYMBOLICNAME, BUNDLE1.getSymbolicName(),
+                    KEY_VERSION, BUNDLE1.getVersion() }));
+        versions.appendChild(generateDeploymentVersion(doc, "target'\"", VERSION3, new String[] {
+            BUNDLE1.getUrl().toString(), KEY_SYMBOLICNAME, BUNDLE1.getSymbolicName(),
+            KEY_VERSION, BUNDLE1.getVersion() }));
+        versions.appendChild(generateDeploymentVersion(doc, " '''' \"\"\"\" ", VERSION4, new String[] {
+            BUNDLE1.getUrl().toString(), KEY_SYMBOLICNAME, BUNDLE1.getSymbolicName(),
+            KEY_VERSION, BUNDLE1.getVersion() }));
+        versions.appendChild(generateDeploymentVersion(doc, "myTarget", "1'0'0", new String[] {
+            BUNDLE1.getUrl().toString(), KEY_SYMBOLICNAME, BUNDLE1.getSymbolicName(),
+            KEY_VERSION, BUNDLE1.getVersion() }));
+
+        // Add a valid deployment version (5.0.0) with no bundle urls (empty package)
+        versions.appendChild(generateDeploymentVersion(doc, EMPTYVERSIONTARGET, VERSION1, new String[] {
+            BUNDLE1.getUrl().toString(), KEY_SYMBOLICNAME, BUNDLE1.getSymbolicName(),
+            KEY_VERSION, BUNDLE1.getVersion() }));
+        versions.appendChild(generateDeploymentVersion(doc, EMPTYVERSIONTARGET, VERSION2));
+
+        versions.appendChild(generateDeploymentVersion(doc, RESOURCETARGET, VERSION1, new String[] {
+            BUNDLE1.getUrl().toString(), KEY_SYMBOLICNAME, BUNDLE1.getSymbolicName(),
+            KEY_VERSION, BUNDLE1.getVersion() },
+            new String[] { RESOURCEPROCESSOR1.getUrl().toString(), DIRECTIVE_ISCUSTOMIZER, "true",
+                KEY_SYMBOLICNAME, RESOURCEPROCESSOR1.getSymbolicName(), KEY_VERSION,
+                RESOURCEPROCESSOR1.getVersion() }, new String[] { ARTIFACT1.getUrl().toString(),
+                DIRECTIVE_KEY_PROCESSORID, "my.processor.pid" }, new String[] {
+                ARTIFACT2.getUrl().toString(), DIRECTIVE_KEY_RESOURCE_ID, "Artifact2",
+                DIRECTIVE_KEY_PROCESSORID, "my.processor.pid" }));
+
+        // transform the document to string
+        TransformerFactory tFactory = TransformerFactory.newInstance();
+        Transformer transformer = null;
+        StringWriter sw = null;
+        try {
+            transformer = tFactory.newTransformer();
+            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+            transformer.setOutputProperty(OutputKeys.INDENT, "no");
+            DOMSource source = new DOMSource(doc);
+            sw = new StringWriter();
+            StreamResult result = new StreamResult(sw);
+            transformer.transform(source, result);
+        }
+        catch (TransformerConfigurationException e) {
+            // Should not happen
+            e.printStackTrace();
+        }
+        catch (TransformerException e) {
+            // Should not happen
+            e.printStackTrace();
+        }
+
+        return sw.toString();
+    }
+
+    /**
+     * Helper method to create the description of a deploymentpacakge with given data.
+     * 
+     * @param doc The document to add the version to.
+     * @param targetText The targetId in the deploymentversion.
+     * @param versionText The version in the deploymentversion.
+     * @param data An array of data for the deployment artifact. [0] is the url, and each following item is
+     *        first a directive key, and a directive value. For example,<br>
+     *        <code>new String[] { "http://mybundle", "somedirective", "somevalue" }</code>
+     * @return
+     */
+    private Node generateDeploymentVersion(Document doc, String targetText, String versionText, String[]... data) {
+        Element deploymentversion = doc.createElement(DEPLOYMENTVERSION_TAG);
+        Element attr = doc.createElement(ATTRIBUTES_TAG);
+        deploymentversion.appendChild(attr);
+
+        // Create and add targetId Tag
+        Element elem = null;
+        elem = doc.createElement(TARGETID_TAG);
+        elem.setTextContent(targetText);
+        attr.appendChild(elem);
+
+        // Create and add versionTag
+        elem = doc.createElement(VERSION_TAG);
+        elem.setTextContent(versionText);
+        attr.appendChild(elem);
+
+        // Create and add empty tagsTag to deploymentversion
+        elem = doc.createElement(TAGS_TAG);
+        deploymentversion.appendChild(elem);
+
+        // create and add bundlesTag
+        elem = doc.createElement(ARTIFACTS_TAG);
+        for (String[] s : data) {
+            Element artifact = doc.createElement(ARTIFACT_TAG);
+            Element url = doc.createElement(URL_TAG);
+            url.setTextContent(s[0]);
+            artifact.appendChild(url);
+            Element directives = doc.createElement(DIRECTIVES_TAG);
+            for (int i = 1; i < s.length; i += 2) {
+                Element directive = doc.createElement(s[i]);
+                directive.setTextContent(s[i + 1]);
+                directives.appendChild(directive);
+            }
+            artifact.appendChild(directives);
+            elem.appendChild(artifact);
+        }
+
+        deploymentversion.appendChild(elem);
+
+        return deploymentversion;
+    }
+
+    /**
+     * Without any checked in data, we should just get back no version,
+     * but the provider should not crash.
+     * 
+     * @throws java.io.IOException
+     */
+    @Test(groups = { UNIT })
+    public void testEmptyRepository() throws IOException {
+        Repository mock = new MockDeploymentRepository("", null);
+        TestUtils.configureObject(m_backend, Repository.class, mock);
+
+        List<String> versions = m_backend.getVersions(TARGET);
+        assert versions.size() == 0 : "From an empty repository, we should get 0 versions, but we get "
+            + versions.size();
+    }
+
+    /**
+     * See if the getVersions() methods normal output works
+     */
+    @Test(groups = { UNIT })
+    public void testGetVersion() throws IOException {
+        List<String> versions = m_backend.getVersions(TARGET);
+        assert versions.size() == 1 : "Expected one version to be found, but found " + versions.size();
+        assert versions.get(0).equals(VERSION1) : "Expected version " + VERSION1 + " but found " + versions.get(0);
+    }
+
+    /**
+     * Test the getVersions method with an illegal version (not in org.osgi.framework.Version format)
+     */
+    @Test(groups = { UNIT })
+    public void testIllegalVersion() throws IOException {
+        // an illegal version should be silently ignored
+        List<String> versions = m_backend.getVersions(INVALIDVERSIONTARGET);
+        assert versions.isEmpty() : "Expected no versions to be found, but found " + versions.size();
+    }
+
+    /**
+     * Test with multiple versions. It expects all versions in an ascending order.
+     */
+    @Test(groups = { UNIT })
+    public void testMultipleVersions() throws IOException {
+        List<String> versions = m_backend.getVersions(MULTIPLEVERSIONTARGET);
+        assert versions.size() == 4 : "Expected three version to be found, but found " + versions.size();
+        // all versions should be in ascending order
+        assert versions.get(0).equals(VERSION1) : "Expected version " + VERSION1 + " but found " + versions.get(0);
+        assert versions.get(1).equals(VERSION2) : "Expected version " + VERSION2 + " but found " + versions.get(1);
+        assert versions.get(2).equals(VERSION3) : "Expected version " + VERSION3 + " but found " + versions.get(2);
+        assert versions.get(3).equals(VERSION4) : "Expected version " + VERSION4 + " but found " + versions.get(3);
+    }
+
+    /**
+     * Test the getBundleData for a single version, returning a single bundle
+     */
+    @Test(groups = { UNIT })
+    public void testSingleBundleSingleVersionBundleData() throws IOException {
+        Collection<ArtifactData> bundleData = m_backend.getBundleData(TARGET, VERSION1);
+        assert bundleData.size() == 1 : "Expected one bundle to be found, but found " + bundleData.size();
+        assert bundleData.contains(BUNDLE1) : "Expected to find bundle " + BUNDLE1.getSymbolicName();
+    }
+
+    /**
+     * Test the getBundleData for a single version, returning a multiple bundles
+     */
+    @Test(groups = { UNIT })
+    public void testMultipleBundleSingleVersionBundleData() throws IOException {
+        Collection<ArtifactData> bundleData = m_backend.getBundleData(MULTIPLEVERSIONTARGET, VERSION1);
+        assert bundleData.size() == 2 : "Expected two bundle to be found, but found " + bundleData.size();
+        assert bundleData.contains(BUNDLE3) : "Expected to find bundle " + BUNDLE3.getSymbolicName();
+        assert bundleData.contains(BUNDLE4) : "Expected to find bundle " + BUNDLE4.getSymbolicName();
+    }
+
+    /**
+     * Test the getBundleData with an illegal version (i.e. a version that doesn't exist)
+     */
+    @Test(groups = { UNIT })
+    public void testInvalidVersionBundleData() throws IOException {
+        try {
+            m_backend.getBundleData(TARGET, INVALIDVERSION);
+            assert false : "Expected an error because version " + INVALIDVERSION + " doesn't exist for target: "
+                + TARGET;
+        }
+        catch (IllegalArgumentException iae) {
+            // expected, because the version doesn't exist
+        }
+    }
+
+    /**
+     * Test the getBundleData with an illegal target (i.e. a target that doesn't exist)
+     */
+    @Test(groups = { UNIT })
+    public void testInvalidTargetBundleData() throws IOException {
+        try {
+            m_backend.getBundleData(INVALIDVERSIONTARGET, VERSION1);
+            assert false : "Expected an error because version " + VERSION1 + " doesn't exist for target: "
+                + INVALIDVERSIONTARGET;
+        }
+        catch (IllegalArgumentException iae) {
+            // expected, because the version doesn't exist
+        }
+    }
+
+    /**
+     * Test the getBundleData for a two versions, returning a single bundle that hasn't changed
+     */
+    @Test(groups = { UNIT })
+    public void testSingleUnchangedBundleMultipleVersions() throws IOException {
+        Collection<ArtifactData> bundleData = m_backend.getBundleData(TARGET, VERSION1, VERSION1);
+        assert bundleData.size() == 1 : "Expect one bundle, got " + bundleData.size();
+        Iterator<ArtifactData> it = bundleData.iterator();
+        while (it.hasNext()) {
+            ArtifactData data = it.next();
+            assert !data.hasChanged() : "The data should not have been changed.";
+        }
+    }
+
+    /**
+     * Test the getBundleData for a two versions, returning multiple bundles that haven't changed
+     */
+    @Test(groups = { UNIT })
+    public void testMultipleBundlesMultipleVersions() throws IOException {
+        Collection<ArtifactData> bundleData = m_backend.getBundleData(MULTIPLEVERSIONTARGET, VERSION1, VERSION1);
+        assert bundleData.size() == 2 : "Expected two bundle to be found, but found " + bundleData.size();
+        Iterator<ArtifactData> it = bundleData.iterator();
+        while (it.hasNext()) {
+            ArtifactData data = it.next();
+            assert !data.hasChanged() : "The data should not have been changed.";
+        }
+    }
+
+    /**
+     * Test the getBundleData for a two versions, where in the second version a bundle is removed
+     */
+    @Test(groups = { UNIT })
+    public void testRemovedBundleMultipleVersions() throws IOException {
+        Collection<ArtifactData> bundleData = m_backend.getBundleData(MULTIPLEVERSIONTARGET, VERSION1, VERSION3);
+        assert bundleData.size() == 1 : "Expected one bundle to be found, but found " + bundleData.size();
+    }
+
+    /**
+     * Test the getBundleData for a two versions, where in the second version a bundle is added
+     */
+    @Test(groups = { UNIT })
+    public void testAddedBundleMultipleVersions() throws IOException {
+        Collection<ArtifactData> bundleData = m_backend.getBundleData(MULTIPLEVERSIONTARGET, VERSION3, VERSION1);
+        assert bundleData.size() == 2 : "Expected two bundle to be found, but found " + bundleData.size();
+        Iterator<ArtifactData> it = bundleData.iterator();
+        while (it.hasNext()) {
+            ArtifactData data = it.next();
+            if (data.getSymbolicName().equals("Bundle4")) {
+                assert !data.hasChanged() : "The data (Bundle4) should not have been changed.";
+            }
+            else {
+                assert data.hasChanged() : "The data (Bundle3) should have been changed.";
+            }
+        }
+    }
+
+    /**
+     * Test the getBundleData for a two versions, where in the second version one bundle has changed and another hasn't
+     */
+    @Test(groups = { UNIT })
+    public void testSingleChangedBundleMultipleVersions() throws IOException {
+        Collection<ArtifactData> bundleData = m_backend.getBundleData(MULTIPLEVERSIONTARGET, VERSION1, VERSION4);
+        assert bundleData.size() == 2 : "Expected two bundles to be found, but found " + bundleData.size();
+        Iterator<ArtifactData> it = bundleData.iterator();
+        while (it.hasNext()) {
+            ArtifactData data = it.next();
+            if (data.equals(BUNDLE3_2)) {
+                assert !data.hasChanged() : "The data should not have been changed.";
+            }
+            else if (data.equals(BUNDLE4_2)) {
+                assert data.hasChanged() : "The data should have been changed.";
+            }
+            else {
+                assert false : "Unknown bundle found";
+            }
+        }
+    }
+
+    /**
+     * Test the getBundleData for a two versions, where two bundles have changed
+     */
+    @Test(groups = { UNIT })
+    public void testMultipleChangedBundlesMultipleVersions() throws IOException {
+        Collection<ArtifactData> bundleData = m_backend.getBundleData(MULTIPLEVERSIONTARGET, VERSION1, VERSION2);
+        assert bundleData.size() == 2 : "Expected two bundles to be found, but found " + bundleData.size();
+        Iterator<ArtifactData> it = bundleData.iterator();
+        while (it.hasNext()) {
+            ArtifactData data = it.next();
+            if (data.equals(BUNDLE4_1)) {
+                assert data.hasChanged() : "The data should have been changed.";
+            }
+            else if (data.equals(BUNDLE5)) {
+                assert data.hasChanged() : "The data should have been changed.";
+            }
+            else {
+                assert false : "Unknown bundle found";
+            }
+        }
+    }
+
+    /**
+     * See if the getVersions() methods normal output works with literals ' and "
+     */
+    @Test(groups = { UNIT })
+    public void testGetLiteralTargetVersion() throws IOException {
+        List<String> versions = m_backend.getVersions("'");
+        assert versions.size() == 1 : "Expected one version to be found, but found " + versions.size();
+        assert versions.get(0).equals(VERSION1) : "Expected version " + VERSION1 + " but found " + versions.get(0);
+
+        versions = m_backend.getVersions("\"");
+        assert versions.size() == 1 : "Expected one version to be found, but found " + versions.size();
+        assert versions.get(0).equals(VERSION2) : "Expected version " + VERSION2 + " but found " + versions.get(0);
+
+        versions = m_backend.getVersions("target'\"");
+        assert versions.size() == 1 : "Expected one version to be found, but found " + versions.size();
+        assert versions.get(0).equals(VERSION3) : "Expected version " + VERSION3 + " but found " + versions.get(0);
+
+        versions = m_backend.getVersions(" '''' \"\"\"\" ");
+        assert versions.size() == 1 : "Expected one version to be found, but found " + versions.size();
+        assert versions.get(0).equals(VERSION4) : "Expected version " + VERSION4 + " but found " + versions.get(0);
+    }
+
+    /**
+     * Test the getBundleData for an empty version (no bundle URLS are included)
+     */
+    @Test(groups = { UNIT })
+    public void testEmptyDeploymentVersion() throws IOException {
+        // get the version number
+        List<String> versions = m_backend.getVersions(EMPTYVERSIONTARGET);
+        assert versions.size() == 2 : "Expected two version to be found, but found " + versions.size();
+
+        // get the (empty bundle data version (2))
+        Collection<ArtifactData> bundleData = m_backend.getBundleData(EMPTYVERSIONTARGET, VERSION2);
+        assert bundleData.size() == 0 : "Expected no bundles to be found, but got: " + bundleData.size();
+
+        // check an update from and to an empty version
+        Collection<ArtifactData> bundleData2 = m_backend.getBundleData(EMPTYVERSIONTARGET, VERSION1, VERSION2);
+        assert bundleData2.size() == 0 : "Expected no bundles to be found, but got: " + bundleData2.size();
+
+        Collection<ArtifactData> bundleData3 = m_backend.getBundleData(EMPTYVERSIONTARGET, VERSION2, VERSION1);
+        assert bundleData3.size() == 1 : "Expected one bundle to be found, but got: " + bundleData3.size();
+        assert bundleData3.iterator().next().getVersion().equals("1.0.0");
+    }
+
+    /**
+     * See if a version with a literal is parsed correct and ignored.
+     */
+    @Test(groups = { UNIT })
+    public void testGetLiteralTargetIllegalVersion() throws IOException {
+        List<String> versions = m_backend.getVersions("myTarget");
+        assert versions.size() == 0 : "Expected no versions to be found, but found " + versions.size();
+    }
+
+    /**
+     * Test the getBundleData with some resources.
+     */
+    @Test(groups = { UNIT })
+    public void testBundleDataWithResources() throws IOException {
+        List<String> versions = m_backend.getVersions(RESOURCETARGET);
+        assert versions.size() == 1 : "Expected two version to be found, but found " + versions.size();
+
+        Collection<ArtifactData> bundleData = m_backend.getBundleData(RESOURCETARGET, versions.get(0));
+
+        assert bundleData.size() == 4 : "Expected four bundle to be found, but found " + bundleData.size();
+        Iterator<ArtifactData> it = bundleData.iterator();
+        while (it.hasNext()) {
+            ArtifactData data = it.next();
+            if (data.equals(BUNDLE1)) {
+                // fine
+            }
+            else if (data.equals(RESOURCEPROCESSOR1)) {
+                // fine
+            }
+            else if (data.equals(ARTIFACT1)) {
+                // fine
+            }
+            else if (data.equals(ARTIFACT2)) {
+                // check the filename
+                assert data.getFilename().equals("Artifact2");
+                assert data.getProcessorPid().equals("my.processor.pid");
+            }
+            else {
+                assert false : "Unknown bundle found";
+            }
+        }
+    }
+
+    @Test(groups = { UNIT })
+    public void testArtifactDataManifestGeneration() {
+        Attributes B1NoFixpack = BUNDLE1.getManifestAttributes(false);
+        assert B1NoFixpack.size() == 2;
+        for (Map.Entry<Object, Object> entry : B1NoFixpack.entrySet()) {
+            if (entry.getKey().toString().equals(Constants.BUNDLE_SYMBOLICNAME)) {
+                assert entry.getValue().toString().equals(BUNDLE1.getSymbolicName());
+            }
+            else if (entry.getKey().toString().equals(Constants.BUNDLE_VERSION)) {
+                assert entry.getValue().toString().equals(BUNDLE1.getVersion());
+            }
+            else {
+                assert false : "Unknown header found: " + entry.getKey().toString();
+            }
+        }
+
+        Attributes B1Fixpack = BUNDLE1.getManifestAttributes(true);
+        assert B1Fixpack.size() == 3;
+        for (Map.Entry<Object, Object> entry : B1Fixpack.entrySet()) {
+            if (entry.getKey().toString().equals(Constants.BUNDLE_SYMBOLICNAME)) {
+                assert entry.getValue().toString().equals(BUNDLE1.getSymbolicName());
+            }
+            else if (entry.getKey().toString().equals(Constants.BUNDLE_VERSION)) {
+                assert entry.getValue().toString().equals(BUNDLE1.getVersion());
+            }
+            else if (entry.getKey().toString().equals("DeploymentPackage-Missing")) {
+                assert entry.getValue().toString().equals("true");
+            }
+            else {
+                assert false : "Unknown header found: " + entry.getKey().toString();
+            }
+        }
+
+        Attributes R1NoFixpack = RESOURCEPROCESSOR1.getManifestAttributes(false);
+        assert R1NoFixpack.size() == 3 : "We expect 3 headers, but find " + R1NoFixpack.size();
+        for (Map.Entry<Object, Object> entry : R1NoFixpack.entrySet()) {
+            if (entry.getKey().toString().equals(Constants.BUNDLE_SYMBOLICNAME)) {
+                assert entry.getValue().toString().equals(RESOURCEPROCESSOR1.getSymbolicName());
+            }
+            else if (entry.getKey().toString().equals(Constants.BUNDLE_VERSION)) {
+                assert entry.getValue().toString().equals(RESOURCEPROCESSOR1.getVersion());
+            }
+            else if (entry.getKey().toString().equals(DIRECTIVE_ISCUSTOMIZER)) {
+                assert entry.getValue().toString().equals("true");
+            }
+            else {
+                assert false : "Unknown header found: " + entry.getKey().toString();
+            }
+        }
+
+        Attributes A1NoFixpack = ARTIFACT1.getManifestAttributes(false);
+        assert A1NoFixpack.size() == 1 : "We expect 1 headers, but find " + A1NoFixpack.size();
+        for (Map.Entry<Object, Object> entry : A1NoFixpack.entrySet()) {
+            if (entry.getKey().toString().equals(DIRECTIVE_KEY_PROCESSORID)) {
+                assert entry.getValue().toString().equals("my.processor.pid");
+            }
+            else {
+                assert false : "Unknown header found: " + entry.getKey().toString();
+            }
+        }
+    }
+
+    @AfterTest(alwaysRun = true)
+    public void tearDown() throws Exception {
+        FileUtils.removeDirectoryWithContent(m_tempDirectory);
+    }
+
+}

Added: ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/service/impl/DeploymentServiceImplTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/service/impl/DeploymentServiceImplTest.java?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/service/impl/DeploymentServiceImplTest.java (added)
+++ ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/service/impl/DeploymentServiceImplTest.java Thu Apr  4 09:43:34 2013
@@ -0,0 +1,286 @@
+/*
+ * 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.service.impl;
+
+import static org.apache.ace.test.utils.TestUtils.UNIT;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+import java.util.SortedSet;
+
+import org.apache.ace.connectionfactory.ConnectionFactory;
+import org.apache.ace.deployment.Deployment;
+import org.apache.ace.discovery.Discovery;
+import org.apache.ace.identification.Identification;
+import org.apache.ace.test.utils.TestUtils;
+import org.osgi.framework.Version;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.service.log.LogService;
+import org.osgi.service.useradmin.User;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class DeploymentServiceImplTest {
+    
+    private static final Version VERSION1 = new Version("1.0.0");
+    private static final Version VERSION2 = new Version("2.0.0");
+    private static final Version VERSION3 = new Version("3.0.0");
+    
+    private DeploymentServiceImpl m_service;
+    private MockDeployerService m_mockDeployerService;
+    private boolean m_correctVersionInstalled;
+    private boolean m_installCalled;
+
+    @BeforeMethod(alwaysRun = true)
+    protected void setUp() throws Exception {
+        m_mockDeployerService = new MockDeployerService();
+        
+        m_correctVersionInstalled = false;
+        m_installCalled = false;
+        m_service = new DeploymentServiceImpl();
+        
+        TestUtils.configureObject(m_service, LogService.class);
+        TestUtils.configureObject(m_service, EventAdmin.class);
+        TestUtils.configureObject(m_service, ConnectionFactory.class, new MockConnectionFactory());
+        TestUtils.configureObject(m_service, Identification.class, new Identification() {
+            public String getID() {
+                return "test";
+            }
+        });
+        TestUtils.configureObject(m_service, Discovery.class, new Discovery() {
+            public URL discover() {
+                try {
+                    return new URL("http://localhost/");
+                }
+                catch (MalformedURLException e) {
+                    throw new RuntimeException(e);
+                }
+            }
+        });
+        TestUtils.configureObject(m_service, Deployment.class, m_mockDeployerService);
+    }
+
+    @Test(groups = { UNIT })
+    public void testGetHighestLocalVersion() {
+        prepareMockEnvironment(new Version[] {VERSION1, VERSION2, VERSION3}, null, null);
+        Version highestVersion = m_service.getHighestLocalVersion();
+        assert highestVersion.equals(VERSION3) : "Highest local version is incorrect, expected " + VERSION3.toString() + " but got " + highestVersion.toString();
+    }
+
+    @Test(groups = { UNIT })
+    public void testGetRemoteVersionsWithURL() throws MalformedURLException, IOException {
+        URL[] urls =  prepareMockEnvironment(null, new Version[] {VERSION1, VERSION2, VERSION3}, null);
+        SortedSet<Version> highestVersion = m_service.getRemoteVersions(urls[0]);
+        assert !highestVersion.isEmpty() : "Expected versions to return!";
+        assert highestVersion.last().equals(VERSION3) : "Highest remote version is incorrect, expected " + VERSION3.toString() + " but got " + highestVersion.toString();
+    }
+
+    @Test(groups = { UNIT })
+    public void testUpdateWithLatestVersion() throws Exception {
+        final URL[] urls=  prepareMockEnvironment(null, new Version[] {VERSION1, VERSION2, VERSION3}, VERSION3);
+
+        TestUtils.configureObject(m_service, Discovery.class, new Discovery() {
+            public URL discover() {
+                return urls[1];
+            }
+        });
+
+        m_service.update(VERSION3);
+        
+        assert m_installCalled : "Install not called?!";
+        assert m_correctVersionInstalled : "Wrong version installed?!";
+    }
+
+    @Test(groups = { UNIT })
+    public void testUpdateWithNonLatestVersion() throws Exception {
+        final URL[] urls=  prepareMockEnvironment(null, new Version[] {VERSION1, VERSION2, VERSION3}, VERSION2);
+
+        TestUtils.configureObject(m_service, Discovery.class, new Discovery() {
+            public URL discover() {
+                return urls[1];
+            }
+        });
+
+        m_service.update(VERSION2);
+        
+        assert m_installCalled : "Install not called?!";
+        assert m_correctVersionInstalled : "Wrong version installed?!";
+    }
+
+    /**
+     * Helper method to setup the correct endpoints and deploymentservice based on the appropriate mock classes.
+     *
+     * @param localVersions The versions that should appear to be installed.
+     * @param remoteVersions The versions that should appear to be available remotely.
+     * @param expectedInstallVersion The version that is expected to be installed.
+     * @return Array of two urls, element [0] is the controlEndpoint, element [1] is the dataEndpoint
+     */
+    private URL[] prepareMockEnvironment(Version[] localVersions, Version[] remoteVersions, Version expectedInstallVersion) {
+        if (localVersions == null) {
+            localVersions = new Version[0];
+        }
+        if (remoteVersions == null) {
+            remoteVersions = new Version[0];
+        }
+        if (expectedInstallVersion == null) {
+            expectedInstallVersion = Version.emptyVersion;
+        }
+        // mock installed versions
+        m_mockDeployerService.setList(localVersions);
+
+        // mock versions available remotely through the control channel
+        MockURLConnection controlURLConnection = new MockURLConnection();
+        controlURLConnection.setVersions(remoteVersions, null);
+
+        // mock version available remotely through the data channel
+        MockURLConnection dataURLConnection = new MockURLConnection();
+        dataURLConnection.setVersions(new Version[] {expectedInstallVersion}, null);
+
+        m_mockDeployerService.setExpectedInstallVersion(expectedInstallVersion);
+
+        final URL controlEndpoint;
+        URL dataEndpoint = null;
+        try {
+            // create endpoints based on mock classes
+            controlEndpoint = new URL(new URL("http://notmalformed"), "", new MockURLStreamHandler(controlURLConnection));
+            dataEndpoint = new URL(new URL("http://notmalformed"), "", new MockURLStreamHandler(dataURLConnection));
+        }
+        catch (MalformedURLException e) {
+            throw new RuntimeException(e);
+        }
+
+        return new URL[] {controlEndpoint, dataEndpoint};
+    }
+
+    /**
+     * Mock implementation of {@link ConnectionFactory}.
+     */
+    static final class MockConnectionFactory implements ConnectionFactory {
+        public URLConnection createConnection(URL url) throws IOException {
+            return url.openConnection();
+        }
+        
+        public URLConnection createConnection(URL url, User user) throws IOException {
+            return createConnection(url);
+        }
+    }
+
+    /**
+     * Mock implementation of <code>DeploymentService</code> that expects Version objects.
+     * The Version objects that are 'installed' can be mocked with the new <code>setList(Version[] objects)</code>
+     * method. The <code>install(Inputstream is)</code> method only checks if the call was expected by verifying the
+     * version matches the version set by the <code>setExpectedInstallVersion(Version v)</code> method. If so a boolean
+     * in the outer class is set to true.
+     */
+    private class MockDeployerService implements Deployment {
+        Object[] m_objects = new Object[]{};
+        Version m_expectedInstallVersion = Version.emptyVersion;
+
+        public String getName(Object object) throws IllegalArgumentException {
+            return "test";
+        }
+
+        public void setExpectedInstallVersion(Version version) {
+            m_expectedInstallVersion = version;
+        }
+
+        public Version getVersion(Object object) throws IllegalArgumentException {
+            return (Version) object;
+        }
+
+        public Object install(InputStream inputStream) throws Exception {
+            m_installCalled = true;
+            BufferedReader bufReader = new BufferedReader(new InputStreamReader(inputStream));
+            String versionString = bufReader.readLine();
+            if (m_expectedInstallVersion.equals(new Version(versionString))) {
+                m_correctVersionInstalled = true;
+            }
+            return new Version(versionString);
+        }
+
+        public Object[] list() {
+            return m_objects;
+        }
+
+        public void setList(Version[] objects) {
+            m_objects = objects;
+        }
+
+    }
+
+    /**
+     * Mock implementation of <code>URLStreamHandler</code>. Will return the <code>URLConnection</code>
+     * supplied in the constructor instead when <code>openConnection(URL url)</code> is called.
+     */
+    private static class MockURLStreamHandler extends URLStreamHandler {
+        private final URLConnection urlConn;
+
+        public MockURLStreamHandler(URLConnection urlConnection) {
+            this.urlConn = urlConnection;
+        }
+
+        @Override
+        protected URLConnection openConnection(URL url) throws IOException {
+            return urlConn;
+        }
+    }
+
+    /**
+     * Mock implementation of <code>URLConnection</code>. Instead of returning an inputstream
+     * based on the URL it will return an inputstream based on the versions specified by the
+     * new <code>setVersions(Version[] versions)</code> method.
+     */
+    private static class MockURLConnection extends URLConnection {
+        private ByteArrayInputStream m_inputStream = new ByteArrayInputStream(new byte[]{});
+
+        protected MockURLConnection() {
+            super(null);
+        }
+
+        @Override
+        public void connect() throws IOException {
+            // do nothing
+        }
+
+        @Override
+        public InputStream getInputStream() {
+            return m_inputStream;
+        }
+
+        public void setVersions(Version[] versions, String malformedVersion) {
+            String versionsString = "";
+            for(int i = 0; i < versions.length; i++) {
+                versionsString += versions[i] + "\n";
+            }
+            if (malformedVersion != null) {
+                versionsString += malformedVersion + "\n";
+            }
+            byte[] bytes = versionsString.getBytes();
+            m_inputStream = new ByteArrayInputStream(bytes);
+        }
+
+    }
+}

Added: ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/servlet/DeploymentServletTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/servlet/DeploymentServletTest.java?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/servlet/DeploymentServletTest.java (added)
+++ ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/servlet/DeploymentServletTest.java Thu Apr  4 09:43:34 2013
@@ -0,0 +1,232 @@
+/*
+ * 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 java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.ServletOutputStream;
+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.osgi.service.log.LogService;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class DeploymentServletTest {
+
+    private DeploymentServlet m_servlet;
+
+    private HttpServletRequest m_request;
+    private String m_requestCurrentParameter;
+    private String m_requestPathInfo;
+
+    private HttpServletResponse m_response;
+    private ByteArrayOutputStream m_responseOutputStream;
+    private int m_responseStatus;
+
+    private DeploymentProvider m_provider;
+    private List<String> m_providerVersions;
+
+    private StreamGenerator m_generator;
+    private InputStream m_generatorResultStream;
+    private String m_generatorId;
+    private String m_generatorFromVersion;
+    private String m_generatorToVersion;
+
+
+    @BeforeMethod(alwaysRun = true)
+    protected void setUp() throws Exception {
+        // resets variables that store results of tests
+        m_generatorResultStream = null;
+        m_generatorId = null;
+        m_generatorFromVersion = null;
+        m_generatorToVersion = null;
+        m_providerVersions = null;
+
+        // create mock stream generator
+        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 mock deployment provider
+        m_provider = new DeploymentProvider() {
+            public List<ArtifactData> getBundleData(String targetId, String version) throws IllegalArgumentException {
+                return null; // not used
+            }
+            public List<ArtifactData> getBundleData(String targetId, String versionFrom, String versionTo) throws IllegalArgumentException {
+                return null; // not used
+            }
+            public List<String> getVersions(String targetId) throws IllegalArgumentException {
+                if (m_providerVersions == null) {
+                    throw new IllegalArgumentException();
+                }
+                return m_providerVersions;
+            }
+        };
+
+        // create a HttpServletRequest mock object
+        m_request = createMockObjectAdapter(HttpServletRequest.class, new Object() {
+            @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 ServletOutputStream getOutputStream() {
+                return new ServletOutputStream() {
+                    @Override
+                    public void write(int b) throws IOException {
+                        m_responseOutputStream.write(b);
+                    }
+                };
+            }
+            @SuppressWarnings("unused")
+            public void sendError(int status) {
+                m_responseStatus = status;
+            }
+            @SuppressWarnings("unused")
+            public void sendError(int status, String desc) {
+                sendError(status);
+            }
+        });
+
+        m_responseStatus = HttpServletResponse.SC_OK;
+        m_responseOutputStream = new ByteArrayOutputStream();
+
+        // 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);
+
+    }
+
+    @AfterMethod(alwaysRun = true)
+    public void tearDown() throws Exception {
+    }
+
+    @Test(groups = { UNIT })
+    public void getDataForExistingTarget() throws Exception {
+        m_requestPathInfo = "/T1/versions/2.0.0";
+        m_generatorResultStream = new ByteArrayInputStream(new byte[10]);
+        m_providerVersions = new ArrayList<String>();
+        m_providerVersions.add("2.0.0");
+        m_servlet.doGet(m_request, m_response);
+
+        // make sure the request went fine
+        assert m_responseStatus == HttpServletResponse.SC_OK : "We should have got response code " + HttpServletResponse.SC_OK + " and we got " + m_responseStatus;
+        assert m_responseOutputStream.size() == 10 : "We should have got a (dummy) deployment package of 10 bytes.";
+        assert m_generatorId.equals("T1") : "Wrong target ID.";
+        assert m_generatorToVersion.equals("2.0.0") : "Wrong version.";
+    }
+
+    @Test(groups = { UNIT })
+    public void getFixPackageForExistingTarget() throws Exception {
+        m_requestPathInfo = "/T1/versions/2.0.0";
+        m_requestCurrentParameter = "1.0.0";
+        m_generatorResultStream = new ByteArrayInputStream(new byte[10]);
+        m_providerVersions = new ArrayList<String>();
+        m_providerVersions.add("2.0.0");
+        m_servlet.doGet(m_request, m_response);
+
+        // make sure the request went fine
+        assert m_responseStatus == HttpServletResponse.SC_OK : "We should have got response code " + HttpServletResponse.SC_OK + " and we got " + m_responseStatus;
+        assert m_responseOutputStream.size() == 10 : "We should have got a (dummy) deployment package of 10 bytes.";
+        assert m_generatorId.equals("T1") : "Wrong target ID.";
+        assert m_generatorToVersion.equals("2.0.0") : "Wrong version.";
+        assert m_generatorFromVersion.equals("1.0.0") : "Wrong current version.";
+    }
+
+    @Test(groups = { UNIT })
+    public void getDataForNonExistingTarget() throws Exception {
+        m_requestPathInfo = "/T?/versions/2.0.0";
+        m_servlet.doGet(m_request, m_response);
+        assert m_responseStatus == HttpServletResponse.SC_NOT_FOUND : "We should have gotten response code" + HttpServletResponse.SC_NOT_FOUND + ", actual code: " + m_responseStatus;
+    }
+
+    @Test(groups = { UNIT })
+    public void getDataForBadURL() throws Exception {
+        HttpServletRequest garbage = createMockObjectAdapter(HttpServletRequest.class, new Object() {
+            @SuppressWarnings("unused")
+            public String getPathInfo() {
+                return "/";
+            }
+        });
+        m_servlet.doGet(garbage, m_response);
+        assert m_responseStatus == HttpServletResponse.SC_BAD_REQUEST : "We should have gotten response code " + HttpServletResponse.SC_NOT_FOUND + ", actual code: " + m_responseStatus;
+    }
+
+
+    @Test(groups = { UNIT })
+    public void getVersionsExistingTarget() throws Exception {
+        m_requestPathInfo = "/T1/versions";
+        m_providerVersions = new ArrayList<String>();
+        m_providerVersions.add("2.0.0");
+        m_servlet.doGet(m_request, m_response);
+        assert "2.0.0\n".equals(m_responseOutputStream.toString()) : "Expected to get version 2.0.0 in the response";
+    }
+
+    @Test(groups = { UNIT })
+    public void getVersionsNonExistingTarget() throws Exception {
+        m_requestPathInfo = "/T1/versions";
+        m_servlet.doGet(m_request, m_response);
+        assert "".equals(m_responseOutputStream.toString()) : "Expected to get an empty response";
+    }
+
+}

Added: ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/streamgenerator/impl/StreamTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/streamgenerator/impl/StreamTest.java?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/streamgenerator/impl/StreamTest.java (added)
+++ ace/trunk/org.apache.ace.deployment/test/org/apache/ace/deployment/streamgenerator/impl/StreamTest.java Thu Apr  4 09:43:34 2013
@@ -0,0 +1,327 @@
+/*
+ * 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.streamgenerator.impl;
+
+import static org.apache.ace.test.utils.TestUtils.BROKEN;
+import static org.apache.ace.test.utils.TestUtils.UNIT;
+import static org.ops4j.pax.swissbox.tinybundles.core.TinyBundles.newBundle;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.HashSet;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+
+import org.apache.ace.connectionfactory.ConnectionFactory;
+import org.apache.ace.deployment.provider.DeploymentProvider;
+import org.apache.ace.deployment.util.test.TestProvider;
+import org.apache.ace.test.constants.TestConstants;
+import org.apache.ace.test.utils.TestUtils;
+import org.osgi.service.log.LogService;
+import org.osgi.service.useradmin.User;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+/**
+ * Unit tests for the deployment admin stream.
+ */
+public class StreamTest {
+    private static final int COPY_BUFFER_SIZE = 4096;
+
+    private StreamGeneratorImpl m_generator;
+    private TestProvider m_provider;
+
+    @BeforeTest(alwaysRun = true)
+    protected void setUp() throws Exception {
+        m_generator = new StreamGeneratorImpl();
+        m_provider = new TestProvider();
+        InputStream is = newBundle().build(); // TODO this is a very trivial bundle, put more data in?
+        File temp = File.createTempFile("bundle", "jar");
+        temp.deleteOnExit();
+        FileOutputStream fos = new FileOutputStream(temp);
+        byte[] buf = new byte[4096];
+        int b = is.read(buf);
+        while (b != -1) {
+            fos.write(buf, 0, b);
+            b = is.read(buf);
+        }
+        fos.close();
+        is.close();
+        URL url = temp.toURI().toURL();
+        
+        m_provider.addData("A1.jar", "A1", url, "1.0.0", true);
+        m_provider.addData("A2.jar", "A2", url, "1.0.0", false);
+        m_provider.addData("A3.jar", "A3", url, "1.0.0", true);
+        TestUtils.configureObject(m_generator, DeploymentProvider.class, m_provider);
+        TestUtils.configureObject(m_generator, LogService.class);
+        TestUtils.configureObject(m_generator, ConnectionFactory.class, new MockConnectionFactory());
+    }
+
+    public static void main(String[] args) {
+        final InputStream[] streams = new InputStream[300];
+        for (int i = 1; i <= 250; i++) {
+            final String id = "target-" + i;
+            try {
+                streams[i - 1] = new URL("http://127.0.0.1:" + TestConstants.PORT + "/data/" + id + "/versions/1.0.0").openStream();
+            }
+            catch (IOException ex) {
+                ex.printStackTrace();
+            }
+        }
+        new Thread() {
+            @Override
+            public void run() {
+                int done = 0;
+                while (done < 50) {
+                    for (int i = 0; i < 50; i++) {
+                        try {
+                            int in = streams[i].read();
+                            if (in == -1) {
+                                System.out.println(1);
+                                done++;
+                            }
+                        }
+                        catch (IOException e) {
+                            // TODO Auto-generated catch block
+                            e.printStackTrace();
+                        }
+                    }
+                }
+            }
+        }.start();
+        new Thread() {
+            @Override
+            public void run() {
+                int done = 0;
+                while (done < 50) {
+                    for (int i = 50; i < 100; i++) {
+                        try {
+                            int in = streams[i].read();
+                            if (in == -1) {
+                                System.out.println(2);
+                                done++;
+                            }
+                        }
+                        catch (IOException e) {
+                            // TODO Auto-generated catch block
+                            e.printStackTrace();
+                        }
+                    }
+                }
+            }
+        }.start();
+        new Thread() {
+            @Override
+            public void run() {
+                int done = 0;
+                while (done < 50) {
+                    for (int i = 100; i < 150; i++) {
+                        try {
+                            int in = streams[i].read();
+                            if (in == -1) {
+                                System.out.println(3);
+                                done++;
+                            }
+                        }
+                        catch (IOException e) {
+                            // TODO Auto-generated catch block
+                            e.printStackTrace();
+                        }
+                    }
+                }
+            }
+        }.start();
+        new Thread() {
+            @Override
+            public void run() {
+                int done = 0;
+                while (done < 50) {
+                    for (int i = 150; i < 200; i++) {
+                        try {
+                            int in = streams[i].read();
+                            if (in == -1) {
+                                System.out.println(4);
+                                done++;
+                            }
+                        }
+                        catch (IOException e) {
+                            // TODO Auto-generated catch block
+                            e.printStackTrace();
+                        }
+                    }
+                }
+            }
+        }.start();
+        new Thread() {
+            @Override
+            public void run() {
+                int done = 0;
+                while (done < 50) {
+                    for (int i = 200; i < 250; i++) {
+                        try {
+                            int in = streams[i].read();
+                            if (in == -1) {
+                                System.out.println(5);
+                                done++;
+                            }
+                        }
+                        catch (IOException e) {
+                            // TODO Auto-generated catch block
+                            e.printStackTrace();
+                        }
+                    }
+                }
+            }
+        }.start();
+        new Thread() {
+            @Override
+            public void run() {
+                int done = 0;
+                while (done < 50) {
+                    for (int i = 250; i < 300; i++) {
+                        try {
+                            if (streams[i] == null) {
+                                streams[i] = new URL("http://127.0.0.1:" + TestConstants.PORT + "/data/target-" + (i + 1) + "/versions/1.0.0").openStream();
+                            }
+                            int in = streams[i].read();
+                            if (in == -1) {
+                                System.out.println(5);
+                                done++;
+                            }
+                        }
+                        catch (IOException e) {
+                            // TODO Auto-generated catch block
+                            e.printStackTrace();
+                        }
+                    }
+                }
+            }
+        }.start();
+    }
+
+    /**
+     * The specification requires the stream to be readable by JarInputStream (114.3) so make sure it is.
+     */
+    @Test(groups = { UNIT })
+    public void isJarInputStreamReadable() throws Exception {
+        isJarInputStreamReadable(new JarInputStream(m_generator.getDeploymentPackage("test", "1.0.0")), false);
+        isJarInputStreamReadable(new JarInputStream(m_generator.getDeploymentPackage("test", "0.0.0", "1.0.0")), true);
+    }
+
+    private void isJarInputStreamReadable(JarInputStream jis, boolean fixPackage) throws Exception {
+        assert jis != null : "We should have got an input stream for this deployment package.";
+        Manifest m = jis.getManifest();
+        assert m != null : "The stream should contain a valid manifest.";
+        Attributes att = m.getMainAttributes();
+        assert att.getValue("DeploymentPackage-SymbolicName").equals("test");
+        assert att.getValue("DeploymentPackage-Version").equals("1.0.0");
+        assert (fixPackage && att.getValue("DeploymentPackage-FixPack").equals("[0.0.0,1.0.0)")) || (att.getValue("DeploymentPackage-FixPack") == null);
+        HashSet<String> names = new HashSet<String>();
+        JarEntry e = jis.getNextJarEntry();
+        while (e != null) {
+            String name = e.getName();
+            names.add(name);
+            if (fixPackage && name.equals("A2.jar")) {
+                assert e.getAttributes().getValue("DeploymentPackage-Missing").equals("true");
+            }
+            // we could check the name here against the manifest
+            // and make sure we actually get what was promised
+            Attributes a = m.getAttributes(name);
+            assert a != null : "The stream should contain a named section for " + name + " in the manifest.";
+
+            byte[] buffer = new byte[COPY_BUFFER_SIZE];
+            int bytes = jis.read(buffer);
+            while (bytes != -1) {
+                bytes = jis.read(buffer);
+            }
+
+            // get the next entry, if any
+            e = jis.getNextJarEntry();
+        }
+        if (!fixPackage) {
+            assert names.size() == 3 : "The stream should have contained three resources.";
+        }
+        else {
+            assert names.size() == 2 : "The stream should have contained three resources";
+        }
+        assert names.contains("A1.jar") : "The stream should have contained a resource called A1.jar";
+        assert fixPackage ^ names.contains("A2.jar") : "The stream should have contained a resource called A2.jar";
+        assert names.contains("A3.jar") : "The stream should have contained a resource called A3.jar";
+    }
+
+    /**
+     * Test reading 100 streams sequentially.
+     */
+    @Test(groups = { UNIT, BROKEN })
+    public void hundredStreamsSequentially() throws Exception {
+        for (int i = 0; i < 100; i++) {
+            isJarInputStreamReadable();
+        }
+    }
+
+    private Exception m_failure;
+
+    /**
+     * Test reading 100 streams concurrently.
+     */
+    @Test(groups = { UNIT, BROKEN }) // marked broken after discussing it with Karl
+    public void hundredStreamsConcurrently() throws Exception {
+        ExecutorService e = Executors.newFixedThreadPool(5);
+        for (int i = 0; i < 10; i++) {
+            e.execute(new Runnable() {
+                public void run() {
+                    for (int i = 0; i < 10; i++) {
+                        try {
+                            isJarInputStreamReadable();
+                        }
+                        catch (Exception e) {
+                            m_failure = e;
+                        }
+                    }
+                }
+            });
+        }
+        e.shutdown();
+        e.awaitTermination(10, TimeUnit.SECONDS);
+
+        assert m_failure == null : "Test failed: " + m_failure.getLocalizedMessage();
+    }
+
+    /**
+     * Mock implementation of {@link ConnectionFactory}.
+     */
+    static final class MockConnectionFactory implements ConnectionFactory {
+        public URLConnection createConnection(URL url) throws IOException {
+            return url.openConnection();
+        }
+        
+        public URLConnection createConnection(URL url, User user) throws IOException {
+            return createConnection(url);
+        }
+    }
+}

Added: ace/trunk/org.apache.ace.deployment/util.test.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.deployment/util.test.bnd?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.deployment/util.test.bnd (added)
+++ ace/trunk/org.apache.ace.deployment/util.test.bnd Thu Apr  4 09:43:34 2013
@@ -0,0 +1 @@
+Export-Package: org.apache.ace.deployment.util.test
\ No newline at end of file

Modified: ace/trunk/org.apache.ace.obr/test/org/apache/ace/obr/metadata/bindeximpl/BindexMetadataTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.obr/test/org/apache/ace/obr/metadata/bindeximpl/BindexMetadataTest.java?rev=1464402&r1=1464401&r2=1464402&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.obr/test/org/apache/ace/obr/metadata/bindeximpl/BindexMetadataTest.java (original)
+++ ace/trunk/org.apache.ace.obr/test/org/apache/ace/obr/metadata/bindeximpl/BindexMetadataTest.java Thu Apr  4 09:43:34 2013
@@ -26,9 +26,9 @@ import java.io.FileReader;
 
 import org.apache.ace.deployment.provider.ArtifactData;
 import org.apache.ace.deployment.provider.impl.ArtifactDataImpl;
+import org.apache.ace.deployment.util.test.BundleStreamGenerator;
 import org.apache.ace.obr.metadata.MetadataGenerator;
 import org.apache.ace.obr.metadata.bindex.BIndexMetadataGenerator;
-import org.apache.ace.test.utils.deployment.BundleStreamGenerator;
 import org.testng.annotations.Test;
 
 public class BindexMetadataTest {

Modified: ace/trunk/org.apache.ace.repository.ext/bnd.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.repository.ext/bnd.bnd?rev=1464402&r1=1464401&r2=1464402&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.repository.ext/bnd.bnd (original)
+++ ace/trunk/org.apache.ace.repository.ext/bnd.bnd Thu Apr  4 09:43:34 2013
@@ -4,8 +4,7 @@
 	org.apache.ace.test;version=latest,\
 	org.apache.ace.range.api;version=latest,\
 	org.apache.ace.repository.api;version=latest,\
-	org.apache.ace.connectionfactory;version=latest,\
-	org.apache.ace.deployment.provider.api;version=latest
+	org.apache.ace.connectionfactory;version=latest
 Export-Package: org.apache.ace.repository.ext,\
 	org.apache.ace.repository.ext.impl
 Bundle-Version: 1.0.0
\ No newline at end of file

Modified: ace/trunk/org.apache.ace.test/bnd.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.test/bnd.bnd?rev=1464402&r1=1464401&r2=1464402&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.test/bnd.bnd (original)
+++ ace/trunk/org.apache.ace.test/bnd.bnd Thu Apr  4 09:43:34 2013
@@ -2,10 +2,8 @@
 	osgi.core,\
 	osgi.cmpn,\
 	junit.osgi,\
-	org.apache.felix.dependencymanager,\
-	org.apache.ace.deployment.provider.api;version=latest
+	org.apache.felix.dependencymanager
 Export-Package: org.apache.ace.it,\
 	org.apache.ace.test.constants,\
-	org.apache.ace.test.utils,\
-	org.apache.ace.test.utils.deployment
+	org.apache.ace.test.utils
 Bundle-Version: 1.0.0

Added: ace/trunk/org.apache.ace.verifier/.classpath
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.verifier/.classpath?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.verifier/.classpath (added)
+++ ace/trunk/org.apache.ace.verifier/.classpath Thu Apr  4 09:43:34 2013
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" output="bin_test" path="test"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="aQute.bnd.classpath.container"/>
+	<classpathentry kind="con" path="org.testng.TESTNG_CONTAINER"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>

Added: ace/trunk/org.apache.ace.verifier/.project
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.verifier/.project?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.verifier/.project (added)
+++ ace/trunk/org.apache.ace.verifier/.project Thu Apr  4 09:43:34 2013
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.apache.ace.verifier</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>bndtools.core.bndbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>bndtools.core.bndnature</nature>
+	</natures>
+</projectDescription>

Added: ace/trunk/org.apache.ace.verifier/.settings/org.eclipse.jdt.core.prefs
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.verifier/.settings/org.eclipse.jdt.core.prefs?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.verifier/.settings/org.eclipse.jdt.core.prefs (added)
+++ ace/trunk/org.apache.ace.verifier/.settings/org.eclipse.jdt.core.prefs Thu Apr  4 09:43:34 2013
@@ -0,0 +1,11 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.6

Added: ace/trunk/org.apache.ace.verifier/bnd.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.verifier/bnd.bnd?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.verifier/bnd.bnd (added)
+++ ace/trunk/org.apache.ace.verifier/bnd.bnd Thu Apr  4 09:43:34 2013
@@ -0,0 +1,22 @@
+-buildpath: \
+	osgi.core;version=4.3.1,\
+	osgi.cmpn;version=4.3.1,\
+	javax.servlet,\
+	org.apache.felix.dependencymanager,\
+	org.ops4j.pax.swissbox.tinybundles,\
+	org.ops4j.base.store,\
+	commons-logging,\
+	com.vaadin,\
+	org.apache.ace.authentication.api;version=latest,\
+	org.apache.ace.identification.api;version=latest,\
+	org.apache.ace.discovery.api;version=latest,\
+	org.apache.ace.connectionfactory;version=latest,\
+	org.apache.ace.repository.api;version=latest,\
+	org.apache.ace.repository.ext;version=latest,\
+	org.apache.ace.scheduler.api;version=latest,\
+	org.apache.ace.range.api;version=latest,\
+	org.apache.ace.client.repository.api;version=latest,\
+	org.apache.ace.test;version=latest,\
+	org.apache.ace.gateway.log.store;version=latest,\
+	org.apache.ace.webui.vaadin;version=latest
+-sub: *.bnd

Added: ace/trunk/org.apache.ace.verifier/build.xml
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.verifier/build.xml?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.verifier/build.xml (added)
+++ ace/trunk/org.apache.ace.verifier/build.xml Thu Apr  4 09:43:34 2013
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="project" default="build">
+
+	<!-- -->
+
+	<import file="../cnf/build.xml" />
+</project>



Mime
View raw message