You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ma...@apache.org on 2009/06/27 17:53:26 UTC

svn commit: r788992 [20/25] - in /incubator/ace/trunk: gateway/ gateway/src/ gateway/src/net/ gateway/src/net/luminis/ gateway/src/net/luminis/liq/ gateway/src/net/luminis/liq/bootstrap/ gateway/src/net/luminis/liq/bootstrap/multigateway/ gateway/src/n...

Added: incubator/ace/trunk/test/src/net/luminis/liq/client/repository/impl/MockRepository.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/client/repository/impl/MockRepository.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/client/repository/impl/MockRepository.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/client/repository/impl/MockRepository.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,33 @@
+package net.luminis.liq.client.repository.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import net.luminis.liq.repository.Repository;
+import net.luminis.liq.repository.SortedRangeSet;
+
+public class MockRepository implements Repository {
+    private byte[] m_repo;
+    private int currentVersion = 0;
+
+    public InputStream checkout(long version) throws IOException, IllegalArgumentException {
+        if (version == currentVersion) {
+            return new ByteArrayInputStream(m_repo);
+        }
+        return null;
+    }
+
+    public boolean commit(InputStream data, long fromVersion) throws IOException, IllegalArgumentException {
+        if (fromVersion == currentVersion) {
+            currentVersion++;
+            m_repo = AdminTestUtil.copy(data);
+            return true;
+        }
+        return false;
+    }
+
+    public SortedRangeSet getRange() throws IOException {
+        return new SortedRangeSet(new long[] {currentVersion});
+    }
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/client/repository/impl/ModelTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/client/repository/impl/ModelTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/client/repository/impl/ModelTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/client/repository/impl/ModelTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,680 @@
+package net.luminis.liq.client.repository.impl;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.luminis.liq.client.repository.Association;
+import net.luminis.liq.client.repository.ObjectRepository;
+import net.luminis.liq.client.repository.RepositoryUtil;
+import net.luminis.liq.client.repository.helper.bundle.BundleHelper;
+import net.luminis.liq.client.repository.helper.bundle.impl.BundleHelperImpl;
+import net.luminis.liq.client.repository.object.Artifact2GroupAssociation;
+import net.luminis.liq.client.repository.object.ArtifactObject;
+import net.luminis.liq.client.repository.object.DeploymentArtifact;
+import net.luminis.liq.client.repository.object.DeploymentVersionObject;
+import net.luminis.liq.client.repository.object.GatewayObject;
+import net.luminis.liq.client.repository.object.Group2LicenseAssociation;
+import net.luminis.liq.client.repository.object.GroupObject;
+import net.luminis.liq.client.repository.object.LicenseObject;
+import net.luminis.liq.client.repository.repository.Artifact2GroupAssociationRepository;
+import net.luminis.liq.client.repository.repository.ArtifactRepository;
+import net.luminis.liq.client.repository.repository.DeploymentVersionRepository;
+import net.luminis.liq.client.repository.repository.GatewayRepository;
+import net.luminis.liq.client.repository.repository.Group2LicenseAssociationRepository;
+import net.luminis.liq.client.repository.repository.GroupRepository;
+import net.luminis.liq.client.repository.repository.License2GatewayAssociationRepository;
+import net.luminis.liq.client.repository.repository.LicenseRepository;
+import net.luminis.liq.test.utils.TestUtils;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.log.LogService;
+import org.osgi.service.prefs.Preferences;
+import org.osgi.service.prefs.PreferencesService;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+
+/**
+ * Test class for the object model used </code>net.luminis.liq.client.repository<code>.
+ */
+public class ModelTest {
+
+    private ArtifactRepositoryImpl m_artifactRepository;
+    private GroupRepositoryImpl m_groupRepository;
+    private Artifact2GroupAssociationRepositoryImpl m_artifact2groupRepository;
+    private LicenseRepositoryImpl m_licenseRepository;
+    private Group2LicenseAssociationRepositoryImpl m_group2licenseRepository;
+    private GatewayRepositoryImpl m_gatewayRepository;
+    private License2GatewayAssociationRepositoryImpl m_license2gatewayRepository;
+    private DeploymentVersionRepositoryImpl m_deploymentVersionRepository;
+    private RepositoryAdminImpl m_repositoryAdmin;
+
+    private BundleHelperImpl m_bundleHelper = new BundleHelperImpl();
+
+
+    @BeforeMethod(alwaysRun = true)
+    private void initializeRepositoryAdmin() {
+        BundleContext bc = TestUtils.createMockObjectAdapter(BundleContext.class, new Object() {
+            @SuppressWarnings("unused")
+            public Filter createFilter(String filter) throws InvalidSyntaxException {
+                return createLocalFilter(filter);
+            }
+        });
+
+        ChangeNotifier notifier = TestUtils.createNullObject(ChangeNotifier.class);
+
+        m_artifactRepository = new ArtifactRepositoryImpl(notifier);
+        TestUtils.configureObject(m_artifactRepository, LogService.class);
+        TestUtils.configureObject(m_artifactRepository, BundleContext.class, bc);
+        m_artifactRepository.addHelper(BundleHelper.MIMETYPE, m_bundleHelper);
+        m_groupRepository = new GroupRepositoryImpl(notifier);
+        TestUtils.configureObject(m_groupRepository, BundleContext.class, bc);
+        m_artifact2groupRepository = new Artifact2GroupAssociationRepositoryImpl(m_artifactRepository, m_groupRepository, notifier);
+        TestUtils.configureObject(m_artifact2groupRepository, BundleContext.class, bc);
+        m_licenseRepository = new LicenseRepositoryImpl(notifier);
+        TestUtils.configureObject(m_licenseRepository, BundleContext.class, bc);
+        m_group2licenseRepository = new Group2LicenseAssociationRepositoryImpl(m_groupRepository, m_licenseRepository, notifier);
+        TestUtils.configureObject(m_group2licenseRepository, BundleContext.class, bc);
+        m_gatewayRepository = new GatewayRepositoryImpl(notifier);
+        TestUtils.configureObject(m_gatewayRepository, BundleContext.class, bc);
+        m_license2gatewayRepository = new License2GatewayAssociationRepositoryImpl(m_licenseRepository, m_gatewayRepository, notifier);
+        TestUtils.configureObject(m_license2gatewayRepository, BundleContext.class, bc);
+        m_deploymentVersionRepository = new DeploymentVersionRepositoryImpl(notifier);
+        TestUtils.configureObject(m_deploymentVersionRepository, BundleContext.class, bc);
+
+        m_repositoryAdmin = new RepositoryAdminImpl(null, TestUtils.createNullObject(ChangeNotifier.class));
+
+        Map<Class<? extends ObjectRepository>, ObjectRepositoryImpl> repos = new HashMap<Class<? extends ObjectRepository>, ObjectRepositoryImpl>();
+        repos.put(ArtifactRepository.class, m_artifactRepository);
+        repos.put(Artifact2GroupAssociationRepository.class, m_artifact2groupRepository);
+        repos.put(GroupRepository.class, m_groupRepository);
+        repos.put(Group2LicenseAssociationRepository.class, m_group2licenseRepository);
+        repos.put(LicenseRepository.class, m_licenseRepository);
+        repos.put(License2GatewayAssociationRepository.class, m_license2gatewayRepository);
+        repos.put(GatewayRepository.class, m_gatewayRepository);
+        repos.put(DeploymentVersionRepository.class, m_deploymentVersionRepository);
+
+        m_repositoryAdmin.initialize(repos);
+        TestUtils.configureObject(m_repositoryAdmin, Preferences.class);
+        TestUtils.configureObject(m_repositoryAdmin, PreferencesService.class);
+    }
+
+    /**
+     * The bundle object can test functionality coming from
+     * RepositoryObjectImpl, and ArtifactRepository checks much of
+     * ObjectRepositoryImpl.
+     * @throws InvalidSyntaxException
+     */
+    @Test( groups = { TestUtils.UNIT } )
+    public void testBundleObjectAndRepository() throws InvalidSyntaxException {
+        // Create a very simple bundle.
+        ArtifactObject b = createBasicBundleObject("mybundle", "1.0.0");
+
+        // Try to create an illegal one
+        try {
+            createBasicBundleObject("");
+            assert false : "Creating a bundle with an empty name is not allowed.";
+        }
+        catch (IllegalArgumentException iae) {
+            // expected
+        }
+
+        // Even though the bundle is not yet associated to a group, try to get its groups.
+        List<GroupObject> groups = b.getGroups();
+
+        assert groups.size() == 0 : "The bundle is not associated, so it should not return any groups.";
+
+        assert b.getAttribute(BundleHelper.KEY_SYMBOLICNAME).equals("mybundle") : "We should be able to read an attribute we just put in ourselves.";
+
+        b.addTag("mytag", "myvalue");
+
+        assert b.getTag("mytag").equals("myvalue")  : "We should be able to read an attribute we just put in ourselves.";
+        assert b.getTag(BundleHelper.KEY_SYMBOLICNAME) == null : "We should not find an attribute value when asking for a tag.";
+
+        b.addTag(BundleHelper.KEY_SYMBOLICNAME, "mytagname");
+
+        assert b.getTag(BundleHelper.KEY_SYMBOLICNAME).equals("mytagname") : "We can adds tags that have the same name as a bundle, but still return another value.";
+
+        Dictionary<String, Object> dict = b.getDictionary();
+
+        assert dict.get("mytag") == "myvalue" : "The dictionary of the object should contain all tags.";
+        assert dict.get(BundleHelper.KEY_VERSION).equals("1.0.0") : "The dictionary of the object should contain all attributes; we found " + dict.get(BundleHelper.KEY_VERSION);
+        String[] foundNames = (String[]) dict.get(BundleHelper.KEY_SYMBOLICNAME);
+        assert foundNames.length == 2 : "For keys which are used both as a value and as a tag, we should get back both from the dictionary in an array.";
+        assert (foundNames[0].equals("mybundle") && foundNames[1].equals("mytagname")) ||
+        (foundNames[1].equals("mybundle") && foundNames[0].equals("mytagname")) : "The order is undefined, but we should find both the items we put in for '"+BundleHelper.KEY_SYMBOLICNAME+"'.";
+
+        assert m_artifactRepository.get().size() == 1 : "The repository should contain exactly one bundle.";
+        assert m_artifactRepository.get().get(0).equals(b) : "The repository should contain exactly our bundle.";
+
+        ArtifactObject b2 = createBasicBundleObject("myotherbundle", "1");
+
+        assert m_artifactRepository.get(createLocalFilter("(" + BundleHelper.KEY_SYMBOLICNAME + "=mybundle)")).size() == 1 : "When filtering for our bundle, we should find only that.";
+        assert m_artifactRepository.get(createLocalFilter("(" + BundleHelper.KEY_VERSION + "=1.0.0)")).size() == 2 : "When filtering for a version, we should find two bundles.";
+
+        try {
+            createBasicBundleObject("mybundle", "1.0.0");
+            assert false : "Adding a bundle which is identical to one already in the repository should be illegal.";
+        }
+        catch (IllegalArgumentException iae) {
+            //expected
+        }
+
+        try {
+            b2.addAttribute("thenewattribute", "withsomevalue");
+        }
+        catch (UnsupportedOperationException uoe) {
+            assert false : "Adding arbitrary attributes to a bundle object should be allowed.";
+        }
+
+        try {
+            b2.addAttribute(BundleHelper.KEY_SYMBOLICNAME, "bundle.42");
+            assert false : "Changing key attributes in a bundle should not be allowed.";
+        }
+        catch (UnsupportedOperationException uoe) {
+            //expected
+        }
+
+
+        try {
+            Map<String, String> attr = new HashMap<String, String>();
+            attr.put(BundleHelper.KEY_NAME, "mynewbundle");
+            Map<String, String> tags = new HashMap<String, String>();
+            m_artifactRepository.create(attr, tags);
+            assert false : "Creating a bundle without specifying all mandatory atttributes should be illegal.";
+        }
+        catch (IllegalArgumentException iae) {
+            //expected
+        }
+
+
+        m_artifactRepository.remove(b);
+
+        try {
+            b.addTag("mytag", "myvalue");
+            assert false : "Deleted objects are not allowed to be changed.";
+        }
+        catch (IllegalStateException ise) {
+            // expected
+        }
+
+        assert m_artifactRepository.get().size() == 1 : "After removing our first bundle, the repository should contain one bundle.";
+        assert m_artifactRepository.get().get(0).equals(b2) : "After removing our first bundle, the repository should contain only our second bundle.";
+    }
+
+    @Test( groups = { TestUtils.UNIT } )
+    public void testRepositorySerialization() {
+        createBasicBundleObject("mybundle", "1");
+        createBasicBundleObject("mybundle", "2");
+
+        // Write the store to a stream, reset the repository, and re-read it.
+        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+        RepositorySet store = new RepositorySet(null, null, null, null, new ObjectRepositoryImpl[] {m_artifactRepository, m_artifact2groupRepository, m_groupRepository}, null, "", true);
+        new RepositorySerializer(store).toXML(buffer);
+        initializeRepositoryAdmin();
+        store = new RepositorySet(null, null, null, null, new ObjectRepositoryImpl[] {m_artifactRepository, m_artifact2groupRepository, m_groupRepository}, null, "", true);
+        new RepositorySerializer(store).fromXML(new ByteArrayInputStream(buffer.toByteArray()));
+
+        assert m_artifactRepository.get().size() == 2 : "We expect to find 2 bundles, but we find " + m_artifactRepository.get().size();
+    }
+
+    @Test( groups = { TestUtils.UNIT } )
+    public void testSerialization() {
+        ArtifactObject b1 = createBasicBundleObject("bundle1");
+        ArtifactObject b2 = createBasicBundleObject("bundle2");
+        ArtifactObject b3 = createBasicBundleObject("bundle3");
+
+        GroupObject g1 = createBasicGroupObject("group1");
+        GroupObject g2 = createBasicGroupObject("group2");
+
+        m_artifact2groupRepository.create(b1, g1);
+        m_artifact2groupRepository.create(b2, g2);
+        m_artifact2groupRepository.create(b3, g2);
+
+        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+        RepositorySet store = new RepositorySet(null, null, null, null, new ObjectRepositoryImpl[] {m_artifactRepository, m_groupRepository, m_artifact2groupRepository}, null, "", true);
+        new RepositorySerializer(store).toXML(buffer);
+        initializeRepositoryAdmin();
+        store = new RepositorySet(null, null, null, null, new ObjectRepositoryImpl[] {m_artifactRepository, m_groupRepository, m_artifact2groupRepository}, null, "", true);
+        new RepositorySerializer(store).fromXML(new ByteArrayInputStream(buffer.toByteArray()));
+
+        assert m_artifactRepository.get().size() == 3 : "We expect to find 3 bundles, but we find " + m_artifactRepository.get().size();
+        assert m_groupRepository.get().size() == 2 : "We expect to find 2 groups, but we find " + m_groupRepository.get().size();
+        assert m_artifact2groupRepository.get().size() == 3 : "We expect to find 3 associations, but we find " + m_artifact2groupRepository.get().size();
+        assert b1.isAssociated(g1, GroupObject.class) : "After serialization, b1 should still be associated with g1.";
+        assert !b1.isAssociated(g2, GroupObject.class) : "After serialization, b1 should not be associated with g1.";
+        assert !b2.isAssociated(g1, GroupObject.class) : "After serialization, b2 should not be associated with g2.";
+        assert b2.isAssociated(g2, GroupObject.class) : "After serialization, b2 should still be associated with g2.";
+        assert !b3.isAssociated(g1, GroupObject.class) : "After serialization, b3 should not be associated with g2.";
+        assert b3.isAssociated(g2, GroupObject.class) : "After serialization, b3 should still be associated with g2.";
+    }
+
+    @Test( groups = { TestUtils.UNIT } )
+    public void testModelFiltering() throws InvalidSyntaxException {
+        initializeRepositoryAdmin();
+        // Create an empty bundle repository.
+        Map<String, String> attributes = new HashMap<String, String>();
+        attributes.put("myattribute", "theattribute");
+        attributes.put("name", "attname");
+        Map<String, String> tags = new HashMap<String, String>();
+
+        assert m_groupRepository != null : "Something has gone wrong injecting the bundle repository.";
+        GroupObject g1 = m_groupRepository.create(attributes, tags);
+        g1.addTag("mytag", "thetag");
+        g1.addTag("name", "tagname");
+        g1.addTag("difficult", ")diffi)c*ul\\t");
+
+
+        assert m_groupRepository.get(createLocalFilter("(myattribute=*)")).size() == 1 : "There should be a myattribute in b1.";
+        assert m_groupRepository.get(createLocalFilter("(myattribute=theattribute)")).size() == 1 : "There should be myattribute=theattribute in b1.";
+        assert m_groupRepository.get(createLocalFilter("(myattribute=thetag)")).size() == 0 : "There should not be myattribute=thetag in b1.";
+        assert m_groupRepository.get(createLocalFilter("(mytag=*)")).size() == 1 : "There should be a mytag in b1.";
+        assert m_groupRepository.get(createLocalFilter("(mytag=thetag)")).size() == 1 : "There should be mytag=thetag in b1.";
+        assert m_groupRepository.get(createLocalFilter("(mytag=theattribute)")).size() == 0 : "There should not be mytag=theattribute in b1.";
+
+        assert m_groupRepository.get(createLocalFilter("(name=*)")).size() == 1 : "There should be a name parameter in b1.";
+        assert m_groupRepository.get(createLocalFilter("(name=attname)")).size() == 1 : "There should be a name=attname in b1.";
+        assert m_groupRepository.get(createLocalFilter("(name=tagname)")).size() == 1 : "There should be a name=tagname in b1.";
+        assert m_groupRepository.get(createLocalFilter("(name=thetag)")).size() == 0 : "There should not be name=thetag in b1.";
+
+        try {
+            m_groupRepository.get(createLocalFilter("(difficult=)diffi)c*ul\\t"));
+            assert false : "The non-escaped difficult string should raise an error.";
+        }
+        catch (InvalidSyntaxException ex) {
+            //expected
+        }
+        assert m_groupRepository.get(createLocalFilter("(difficult=" + RepositoryUtil.escapeFilterValue(")diffi)c*ul\\t") + ")")).size() == 1 : "The 'difficult' string should be correctly escaped, and thus return exactly one match.";
+    }
+
+    /**
+     * Tests the behavior when associating stuff, and removing associations.
+     */
+    @Test( groups = { TestUtils.UNIT } )
+    public void testAssociations() {
+        initializeRepositoryAdmin();
+        // Create two, rather boring, bundles.
+        ArtifactObject b1 = createBasicBundleObject("bundle1");
+        ArtifactObject b2 = createBasicBundleObject("bundle2");
+
+        // Create three groups.
+        GroupObject g1 = createBasicGroupObject("group1");
+        GroupObject g2 = createBasicGroupObject("group2");
+        GroupObject g3 = createBasicGroupObject("group3");
+
+        // Create some associations.
+        Artifact2GroupAssociation b2g1 = m_artifact2groupRepository.create(b1, g2);
+        assert b2g1 != null;
+        Artifact2GroupAssociation b2g2 = m_artifact2groupRepository.create(b2, g1);
+        assert b2g2 != null;
+        Artifact2GroupAssociation b2g3 = m_artifact2groupRepository.create(b1, g3);
+        assert b2g3 != null;
+        Artifact2GroupAssociation b2g4 = m_artifact2groupRepository.create(b2, g3);
+        assert b2g4 != null;
+
+        // Do some basic checks on the repositories.
+        assert m_artifactRepository.get().size() == 2 : "We should have two bundles in our repository; we found " + m_artifactRepository.get().size() + ".";
+        assert m_groupRepository.get().size() == 3 : "We should have three groups in our repository; we found " + m_groupRepository.get().size() + ".";
+        assert m_artifact2groupRepository.get().size() == 4 : "We should have four associations in our repository; we found " + m_artifact2groupRepository.get().size() + ".";
+
+        assert (b2g4.getLeft().size() == 1) && b2g4.getLeft().contains(b2) : "The left side of the fourth association should be bundle 2.";
+        assert (b2g4.getRight().size() == 1) && b2g4.getRight().contains(g3) : "The right side of the fourth association should be group 3.";
+
+        // Check the wiring: what is wired to what?
+        List<GroupObject> b1groups = b1.getGroups();
+        List<GroupObject> b2groups = b2.getGroups();
+
+        List<ArtifactObject> g1bundles = g1.getArtifacts();
+        List<ArtifactObject> g2bundles = g2.getArtifacts();
+        List<ArtifactObject> g3bundles = g3.getArtifacts();
+        List<LicenseObject> g1licenses = g1.getLicenses();
+        List<LicenseObject> g2licenses = g2.getLicenses();
+        List<LicenseObject> g3licenses = g3.getLicenses();
+
+        assert g1licenses.size() == 0 : "Group one should not have any associations to licenses; we found " + g1licenses.size() + ".";
+        assert g2licenses.size() == 0 : "Group two should not have any associations to licenses; we found " + g2licenses.size() + ".";
+        assert g3licenses.size() == 0 : "Group three should not have any associations to licenses; we found " + g3licenses.size() + ".";
+
+        List<GroupObject> b1expectedGroups = new ArrayList<GroupObject>();
+        b1expectedGroups.add(g2);
+        b1expectedGroups.add(g3);
+        List<GroupObject> b2expectedGroups = new ArrayList<GroupObject>();
+        b2expectedGroups.add(g1);
+        b2expectedGroups.add(g3);
+
+        List<ArtifactObject> g1expectedBundles = new ArrayList<ArtifactObject>();
+        g1expectedBundles.add(b2);
+        List<ArtifactObject> g2expectedBundles = new ArrayList<ArtifactObject>();
+        g2expectedBundles.add(b1);
+        List<ArtifactObject> g3expectedBundles = new ArrayList<ArtifactObject>();
+        g3expectedBundles.add(b1);
+        g3expectedBundles.add(b2);
+
+        assert b1groups.containsAll(b1expectedGroups) && b1expectedGroups.containsAll(b1groups) : "b1 should be associated to exactly groups 2 and 3.";
+        assert b2groups.containsAll(b2expectedGroups) && b2expectedGroups.containsAll(b2groups) : "b2 should be associated to exactly groups 1 and 3.";
+
+        assert g1bundles.containsAll(g1expectedBundles) && g1expectedBundles.containsAll(g1bundles) : "g1 should be associated to exactly bundle 2.";
+        assert g2bundles.containsAll(g2expectedBundles) && g2expectedBundles.containsAll(g2bundles) : "g2 should be associated to exactly bundle 1.";
+        assert g3bundles.containsAll(g3expectedBundles) && g3expectedBundles.containsAll(g3bundles) : "g3 should be associated to exactly bundles 1 and 2.";
+
+        m_artifact2groupRepository.remove(b2g4);
+
+        b1groups = b1.getGroups();
+        b2groups = b2.getGroups();
+        g1bundles = g1.getArtifacts();
+        g2bundles = g2.getArtifacts();
+        g3bundles = g3.getArtifacts();
+
+        b2expectedGroups.remove(g3);
+        g3expectedBundles.remove(b2);
+
+        assert b1groups.containsAll(b1expectedGroups) && b1expectedGroups.containsAll(b1groups) : "b1 should be associated to exactly groups 2 and 3.";
+        assert b2groups.containsAll(b2expectedGroups) && b2expectedGroups.containsAll(b2groups) : "b2 should be associated to exactly group 1.";
+
+        assert g1bundles.containsAll(g1expectedBundles) && g1expectedBundles.containsAll(g1bundles) : "g1 should be associated to exactly bundle 2.";
+        assert g2bundles.containsAll(g2expectedBundles) && g2expectedBundles.containsAll(g2bundles) : "g2 should be associated to exactly bundle 1.";
+        assert g3bundles.containsAll(g3expectedBundles) && g3expectedBundles.containsAll(g3bundles) : "g3 should be associated to exactly bundle 1.";
+    }
+
+
+    /**
+     * Not a full-fledged testcase, but a quick test of the correctness of the
+     * specified classes for groups, licenses and their associations. In essence,
+     * this test 'touches' all code which uses generic code which has been tested
+     * by TestAssociations.
+     */
+    @Test( groups = { TestUtils.UNIT } )
+    public void TestGroup2LicenseAssociations() {
+        initializeRepositoryAdmin();
+        GroupObject g1 = createBasicGroupObject("group1");
+        LicenseObject l1 = createBasicLicenseObject("license1");
+        Group2LicenseAssociation g2l1 = m_group2licenseRepository.create(g1, l1);
+
+        assert (g2l1.getLeft().size() == 1) && g2l1.getLeft().contains(g1) : "Left side of the association should be our group.";
+        assert (g2l1.getRight().size() == 1) &&  g2l1.getRight().contains(l1) : "Right side of the association should be our license.";
+
+        assert g1.getArtifacts().size() == 0 : "Group 1 should not be associated with any bundles; it is associated with " + g1.getArtifacts().size() + ".";
+        assert g1.getLicenses().size() == 1 : "Group 1 should be associated with exactly one license; it is associated with " + g1.getLicenses().size() + ".";
+
+        assert l1.getGroups().size() == 1 : "License 1 should be associated with exactly one group; it is associated with " + l1.getGroups().size() + ".";
+        assert l1.getGateways().size() == 0 : "License 1 should not be associated with any gateways; it is associated with " + l1.getGateways().size() + ".";
+    }
+
+    /**
+     * Not a full-fledged testcase, but a quick test of the correctness of the
+     * specified classes for licenses, gateways and their associations. In essence,
+     * this test 'touches' all code which uses generic code which has been tested
+     * by TestAssociations.
+     */
+    @Test( groups = { TestUtils.UNIT } )
+    public void testLicense2GatewayAssociations() {
+        initializeRepositoryAdmin();
+        LicenseObject l1 = createBasicLicenseObject("license1");
+        GatewayObject g1 = createBasicGatewayObject("gateway1");
+        m_license2gatewayRepository.create(l1, g1);
+
+        assert l1.getGroups().size() == 0 : "License 1 should not be associated with any groups; it is associated with " + l1.getGroups().size() + ".";
+        assert l1.getGateways().size() == 1 : "License 1 should be associated with exactly one gateway; it is associated with " + l1.getGateways().size() + ".";
+
+        assert g1.getLicenses().size() == 1 : "Gateway 1 should be associated with exactly one license; it is associated with " + g1.getLicenses().size() + ".";
+    }
+
+    @Test( groups = { TestUtils.UNIT } )
+    public void testGetAssociationsWith() {
+        initializeRepositoryAdmin();
+        ArtifactObject b1 = createBasicBundleObject("bundle1");
+        GroupObject g1 = createBasicGroupObject("group1");
+        Artifact2GroupAssociation b2g1 = m_artifact2groupRepository.create(b1, g1);
+
+        List<Artifact2GroupAssociation> b1Associations = b1.getAssociationsWith(g1);
+        List<Artifact2GroupAssociation> g1Associations = g1.getAssociationsWith(b1);
+
+        assert b1Associations.size() == 1 : "The bundle has exactly one association to the group, but it shows " + b1Associations.size() + ".";
+        assert b1Associations.get(0) == b2g1 : "The bundle's association should be the one we created.";
+
+        assert g1Associations.size() == 1 : "The group has exactly one association to the bundle.";
+        assert g1Associations.get(0) == b2g1 : "The group's association should be the one we created.";
+    }
+
+    /**
+     * Tests the correctness of the equals() in RepositoryObject.
+     */
+    @Test( groups = { TestUtils.UNIT } )
+    public void testEquals() {
+        List<ArtifactObject> bundles = new ArrayList<ArtifactObject>();
+        bundles.add(createBasicBundleObject("bundle1"));
+        bundles.add(createBasicBundleObject("bundle2"));
+        bundles.get(1).addTag("thetag", "thevalue");
+        bundles.add(createBasicBundleObject("bundle3"));
+
+        List<ArtifactObject> backupBundles = new ArrayList<ArtifactObject>();
+        backupBundles.addAll(bundles);
+
+        for (ArtifactObject b : backupBundles) {
+            bundles.remove(b);
+        }
+
+        assert bundles.size() == 0 : "The bundles list should be empty; if not, the ArtifactObject's equals() could be broken.";
+    }
+
+    @Test( groups = { TestUtils.UNIT } )
+    public void testDeploymentVersion() {
+        DeploymentVersionObject version = createBasicDeploymentVersionObject("gateway1", "1", new String[] {"bundle1", "bundle2"});
+
+        assert version.getDeploymentArtifacts().length == 2 : "We expect to find two bundles, but we find " + version.getDeploymentArtifacts().length;
+        assert version.getDeploymentArtifacts()[0].getUrl().equals("bundle1");
+        assert version.getDeploymentArtifacts()[1].getUrl().equals("bundle2");
+
+        ((DeploymentArtifactImpl) version.getDeploymentArtifacts()[0]).addDirective("myDirective", "myValue");
+
+        try {
+            createBasicDeploymentVersionObject("gateway1", "1", new String[] {"bundle1", "bundle2"});
+            assert false : "Creating a deployment version with a gateway and version that already exists should not be allowed.";
+        }
+        catch (IllegalArgumentException iae) {
+            // expected
+        }
+
+        assert m_deploymentVersionRepository.get().size() == 1 : "The disallowed version should not be in the repository; we find " + m_deploymentVersionRepository.get().size();
+        assert m_deploymentVersionRepository.get().get(0) == version : "Only our newly created version object should be in the repository.";
+
+        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+        RepositorySet deployment = new RepositorySet(null, null, null, null, new ObjectRepositoryImpl[] {m_deploymentVersionRepository}, null, "", true);
+        new RepositorySerializer(deployment).toXML(buffer);
+        initializeRepositoryAdmin();
+
+        assert m_deploymentVersionRepository.get().size() == 0;
+
+        deployment = new RepositorySet(null, null, null, null, new ObjectRepositoryImpl[] {m_deploymentVersionRepository}, null, "", true);
+        new RepositorySerializer(deployment).fromXML(new ByteArrayInputStream(buffer.toByteArray()));
+
+
+        assert m_deploymentVersionRepository.get().size() == 1 : "The disallowed version should not be in the repository.";
+        assert m_deploymentVersionRepository.get().get(0).equals(version) : "Only our newly created version object should be in the repository.";
+
+        assert m_deploymentVersionRepository.get().get(0).getDeploymentArtifacts().length == 2 : "We expect to find two bundles, but we find " + m_deploymentVersionRepository.get().get(0).getDeploymentArtifacts().length;
+        assert m_deploymentVersionRepository.get().get(0).getDeploymentArtifacts()[0].getUrl().equals("bundle1");
+        assert m_deploymentVersionRepository.get().get(0).getDeploymentArtifacts()[0].getKeys().length == 1 : "We expect to find one directive in the first artifact.";
+        assert m_deploymentVersionRepository.get().get(0).getDeploymentArtifacts()[0].getDirective("myDirective").equals("myValue") : "The directive should be 'myValue'.";
+        assert m_deploymentVersionRepository.get().get(0).getDeploymentArtifacts()[1].getUrl().equals("bundle2");
+    }
+
+    @Test( groups = { TestUtils.UNIT } )
+    public void testDeploymentRepository() {
+        DeploymentVersionObject version11 = createBasicDeploymentVersionObject("gateway1", "1", new String[] {"bundle1", "bundle2"});
+        DeploymentVersionObject version12 = createBasicDeploymentVersionObject("gateway1", "2", new String[] {"bundle3", "bundle4"});
+        // Note the different order in adding the versions for gateway2.
+        DeploymentVersionObject version22 = createBasicDeploymentVersionObject("gateway2", "2", new String[] {"bundleC", "bundleD"});
+        DeploymentVersionObject version21 = createBasicDeploymentVersionObject("gateway2", "1", new String[] {"bundleA", "bundleB"});
+
+        assert m_deploymentVersionRepository.getDeploymentVersions("NotMyGateway").size() == 0 : "The deployment repository should not return" +
+        		"any versions when we ask for a gateway that does not exist, but it returns " + m_deploymentVersionRepository.getDeploymentVersions("NotMyGateway").size();
+
+        List<DeploymentVersionObject> for1 = m_deploymentVersionRepository.getDeploymentVersions("gateway1");
+        assert for1.size() == 2 : "We expect two versions for gateway1, but we find " + for1.size();
+        assert for1.get(0) == version11 : "The first version for gateway1 should be version11";
+        assert for1.get(1) == version12 : "The second version for gateway1 should be version12";
+
+        List<DeploymentVersionObject> for2 = m_deploymentVersionRepository.getDeploymentVersions("gateway2");
+        assert for2.size() == 2 : "We expect two versions for gateway2, but we find " + for2.size();
+        assert for2.get(0) == version21 : "The first version for gateway2 should be version21";
+        assert for2.get(1) == version22 : "The second version for gateway2 should be version22";
+
+        assert m_deploymentVersionRepository.getMostRecentDeploymentVersion("NotMyGateway") == null : "The most recent version for a non-existent gateway should not exist.";
+        assert m_deploymentVersionRepository.getMostRecentDeploymentVersion("gateway1") == version12 : "The most recent version for gateway1 should be version12";
+        assert m_deploymentVersionRepository.getMostRecentDeploymentVersion("gateway2") == version22 : "The most recent version for gateway2 should be version22";
+    }
+
+    @Test( groups = { TestUtils.UNIT } )
+    public void testDeploymentRepositoryFilter() {
+
+        String gwId = "\\ ( * ) gateway1)";
+        DeploymentVersionObject version1 = createBasicDeploymentVersionObject(gwId, "1", new String[] {"bundle1", "bundle2"});
+
+        List<DeploymentVersionObject> for1 = m_deploymentVersionRepository.getDeploymentVersions( gwId );
+        assert for1.size() == 1 : "We expect one version for" + gwId + ", but we find " + for1.size();
+        assert for1.get(0) == version1 : "The only version for" + gwId +  "should be version1";
+    }
+
+    @Test( groups = { TestUtils.UNIT } )
+    public void testAssociationsWithLists() {
+        ArtifactObject b1 = createBasicBundleObject("b1");
+        ArtifactObject b2 = createBasicBundleObject("b2");
+        ArtifactObject b3 = createBasicBundleObject("b3");
+        GroupObject g1 = createBasicGroupObject("g1");
+        GroupObject g2 = createBasicGroupObject("g2");
+        GroupObject g3 = createBasicGroupObject("g3");
+
+        List<ArtifactObject> bundles = new ArrayList<ArtifactObject>();
+        bundles.add(b1);
+        bundles.add(b2);
+        List<GroupObject> groups = new ArrayList<GroupObject>();
+        groups.add(g1);
+        groups.add(g3);
+
+        Artifact2GroupAssociation bg = m_artifact2groupRepository.create(bundles, groups);
+
+        assert bg.getLeft().size() == 2 : "We expect two bundles on the left side of the association.";
+        assert bg.getRight().size() == 2 : "We expect two groups on the right side of the association.";
+
+        assert bg.getLeft().contains(b1) : "b1 should be on the left side of the association.";
+        assert bg.getLeft().contains(b2) : "b2 should be on the left side of the association.";
+        assert !bg.getLeft().contains(b3) : "b3 should not be on the left side of the association.";
+        assert bg.getRight().contains(g1) : "g1 should be on the right side of the association.";
+        assert !bg.getRight().contains(g2) : "g2 should not be on the right side of the association.";
+        assert bg.getRight().contains(g3) : "g3 should be on the right side of the association.";
+
+        List<GroupObject> foundGroups = b1.getGroups();
+        assert foundGroups.size() == 2 : "b1 should be associated with two groups.";
+        assert foundGroups.contains(g1) : "b1 should be associated with g1";
+        assert !foundGroups.contains(g2) : "b1 not should be associated with g2";
+        assert foundGroups.contains(g3) : "b1 should be associated with g3";
+
+        foundGroups = b3.getGroups();
+        assert foundGroups.size() == 0 : "b3 should not be associated with any groups.";
+
+        List<ArtifactObject> foundBundles = g3.getArtifacts();
+        assert foundBundles.size() == 2 : "g1 should be associated with two groups.";
+        assert foundBundles.contains(b1) : "g1 should be associated with b1";
+        assert foundBundles.contains(b2) : "g1 should be associated with b2";
+        assert !foundBundles.contains(b3) : "g1 should not be associated with b3";
+    }
+
+    @Test( groups = { TestUtils.UNIT } )
+    public void testAssociationsWithCardinality() {
+        ArtifactObject b1 = createBasicBundleObject("b1");
+        GroupObject g1 = createBasicGroupObject("g1");
+        GroupObject g2 = createBasicGroupObject("g2");
+        GroupObject g3 = createBasicGroupObject("g3");
+
+        Map<String, String> props = new HashMap<String, String>();
+        props.put(Association.LEFT_ENDPOINT, "(" + BundleHelper.KEY_SYMBOLICNAME + "=b1)");
+        props.put(Association.LEFT_CARDINALITY, "1");
+        props.put(Association.RIGHT_ENDPOINT, "(" + GroupObject.KEY_NAME + "=g*)");
+        props.put(Association.RIGHT_CARDINALITY, "2");
+        Map<String, String> tags = new HashMap<String, String>();
+
+        try {
+            m_artifact2groupRepository.create(props, tags);
+            assert false : "There are three matches for the group, but we have a cardinality of 2; we should expect a NPE because no comparator is provided.";
+        }
+        catch (NullPointerException npe) {
+            //expected
+        }
+
+        props.put(Association.RIGHT_CARDINALITY, "3");
+
+        Artifact2GroupAssociation bg = m_artifact2groupRepository.create(props, tags);
+        assert b1.getGroups().size() == 3 : "The bundle should be associated to three groups.";
+        assert (g1.getArtifacts().size() == 1) && g1.getArtifacts().contains(b1) : "g1 should be associated to only b1.";
+        assert (g2.getArtifacts().size() == 1) && g2.getArtifacts().contains(b1) : "g1 should be associated to only b1.";
+        assert (g3.getArtifacts().size() == 1) && g3.getArtifacts().contains(b1) : "g1 should be associated to only b1.";
+    }
+
+    private Filter createLocalFilter(String filter) throws InvalidSyntaxException {
+        return new org.apache.felix.framework.FilterImpl(filter);
+    }
+
+    private ArtifactObject createBasicBundleObject(String symbolicName) {
+        return createBasicBundleObject(symbolicName, null);
+    }
+
+    private ArtifactObject createBasicBundleObject(String symbolicName, String version) {
+        Map<String, String> attr = new HashMap<String, String>();
+        attr.put(BundleHelper.KEY_SYMBOLICNAME, symbolicName);
+        attr.put(ArtifactObject.KEY_MIMETYPE, BundleHelper.MIMETYPE);
+        attr.put(ArtifactObject.KEY_URL, "http://" + symbolicName + "-v" + ((version == null) ? "null" : version));
+        Map<String, String> tags = new HashMap<String, String>();
+
+        if (version != null) {
+            attr.put(BundleHelper.KEY_VERSION, version);
+        }
+        return m_artifactRepository.create(attr, tags);
+    }
+
+    private GroupObject createBasicGroupObject(String name) {
+        Map<String, String> attr = new HashMap<String, String>();
+        attr.put(GroupObject.KEY_NAME, name);
+        Map<String, String> tags = new HashMap<String, String>();
+
+        return m_groupRepository.create(attr, tags);
+    }
+
+    private LicenseObject createBasicLicenseObject(String name) {
+        Map<String, String> attr = new HashMap<String, String>();
+        attr.put(LicenseObject.KEY_NAME, name);
+        Map<String, String> tags = new HashMap<String, String>();
+
+        return m_licenseRepository.create(attr, tags);
+    }
+
+    private GatewayObject createBasicGatewayObject(String id) {
+        Map<String, String> attr = new HashMap<String, String>();
+        attr.put(GatewayObject.KEY_ID, id);
+        Map<String, String> tags = new HashMap<String, String>();
+
+        return m_gatewayRepository.create(attr, tags);
+    }
+
+    private DeploymentVersionObject createBasicDeploymentVersionObject(String gatewayID, String version, String[] bundles) {
+        Map<String, String> attr = new HashMap<String, String>();
+        attr.put(DeploymentVersionObject.KEY_GATEWAYID, gatewayID);
+        attr.put(DeploymentVersionObject.KEY_VERSION, version);
+        Map<String, String> tags = new HashMap<String, String>();
+
+        List<DeploymentArtifactImpl> artifacts = new ArrayList<DeploymentArtifactImpl>();
+        for (String s : bundles) {
+            artifacts.add(new DeploymentArtifactImpl(s));
+        }
+        return m_deploymentVersionRepository.create(attr, tags, artifacts.toArray(new DeploymentArtifact[0]));
+
+    }
+
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/client/repositoryuseradmin/impl/RepositoryUserAdminSerializationTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/client/repositoryuseradmin/impl/RepositoryUserAdminSerializationTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/client/repositoryuseradmin/impl/RepositoryUserAdminSerializationTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/client/repositoryuseradmin/impl/RepositoryUserAdminSerializationTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,260 @@
+package net.luminis.liq.client.repositoryuseradmin.impl;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import net.luminis.liq.repository.SortedRangeSet;
+import net.luminis.liq.repository.ext.CachedRepository;
+import net.luminis.liq.test.utils.TestUtils;
+
+import org.apache.felix.framework.FilterImpl;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.log.LogService;
+import org.osgi.service.prefs.Preferences;
+import org.osgi.service.prefs.PreferencesService;
+import org.osgi.service.useradmin.Group;
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class RepositoryUserAdminSerializationTest {
+
+    private RepositoryUserAdminImpl m_impl;
+
+    private MockCachedRepository m_cachedRepository;
+
+    @BeforeMethod(alwaysRun = true)
+    public void setUp() {
+        m_impl = new RepositoryUserAdminImpl();
+        TestUtils.configureObject(m_impl, BundleContext.class, TestUtils.createMockObjectAdapter(BundleContext.class, new Object() {
+            @SuppressWarnings("unused")
+            public Filter createFilter(String s) throws InvalidSyntaxException {
+                return new FilterImpl(s);
+            }
+        }));
+
+        // We configure the CachedRepository ourselves, so there is no need to login
+        m_cachedRepository = new MockCachedRepository();
+        TestUtils.configureObject(m_impl, CachedRepository.class, m_cachedRepository);
+        TestUtils.configureObject(m_impl, PreferencesService.class);
+        TestUtils.configureObject(m_impl, LogService.class);
+        TestUtils.configureObject(m_impl, Preferences.class); // A Preferences is cached for storing the version.
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test(groups = { UNIT })
+    public void testRepositoryUserAdminSerialization() throws Exception {
+        // Create some data
+        User user = (User) m_impl.createRole("me", Role.USER);
+        user.getProperties().put("fullname", "Mr. M. Me");
+        user.getCredentials().put("password", "swordfish");
+        user.getCredentials().put("certificate", new byte[] {'4', '2'});
+        Group group = (Group) m_impl.createRole("myGroup", Role.GROUP);
+        group.getProperties().put("description", "One group to rule them all.");
+        group.addMember(user);
+
+        // Write it to the store
+        new Thread("RepositoryUserAdmin committer") {
+            @Override
+            public void run() {
+                try {
+                    m_impl.commit();
+                }
+                catch (Exception e) {
+                    System.err.println("Error writing data");
+                    e.printStackTrace(System.err);
+                }
+            }
+        }.start();
+
+        // wait for impl to be ready, and retrieve what he has written
+        Object[] request  = m_cachedRepository.getRequest(true);
+        assert request[0].equals("writeLocal");
+        InputStream input = (InputStream) request[1];
+        request = m_cachedRepository.getRequest(true);
+        assert request[0].equals("commit");
+
+        String data1 = getInputStreamAsString(input);
+
+        // alter the contents
+        m_impl.createRole("otherme", Role.USER);
+        m_impl.removeRole("myGroup");
+
+        m_cachedRepository.addResponse(new ByteArrayInputStream(data1.getBytes()));
+
+        final Semaphore sem = new Semaphore(0);
+
+        // make impl read what it has just written
+        new Thread("RepositoryUserAdmin committer") {
+            @Override
+            public void run() {
+                try {
+                    m_impl.checkout();
+                }
+                catch (Exception e) {
+                    System.err.println("Error reading data");
+                    e.printStackTrace(System.err);
+                }
+                sem.release();
+            }
+        }.start();
+
+        // wait for the reading to be done
+        sem.tryAcquire(5, TimeUnit.SECONDS);
+
+        request = m_cachedRepository.getRequest(true);
+        assert request[0].equals("checkout");
+
+        // inspect the current contents of impl
+        Role[] roles = m_impl.getRoles(null);
+        assert roles.length == 2 : "Found " + roles.length + " roles in stead of 2.";
+        for (Role role : roles) {
+            if (role.equals(user)) {
+                assert user.hasCredential("password", "swordfish");
+                assert user.hasCredential("certificate", new byte[] {'4', '2'});
+            }
+            else if (role.equals(group)) {
+                assert ((Group) role).getMembers().length == 1 : "We expect one member in the group in stream of " + ((Group) role).getMembers().length;
+                assert ((Group) role).getMembers()[0].equals(user);
+            }
+            else {
+                assert false : "Found an unknown role: " + role.toString() + " (" + role.getName() + ")";
+            }
+        }
+    }
+
+    @Test(groups = { UNIT })
+    public void testCircularDependency() throws Exception {
+        Group g1 = (Group) m_impl.createRole("group1", Role.GROUP);
+        Group g2 = (Group) m_impl.createRole("group2", Role.GROUP);
+        g1.addMember(g2);
+        g2.addMember(g1);
+
+        try {
+            m_impl.commit();
+            assert false : "There is a circular dependency, this should be detected and reason for failure.";
+        }
+        catch (IllegalArgumentException iae) {
+            // expected
+        }
+    }
+
+    /**
+     * A mock cached repository, used for checking calls and staging responses to impl.
+     */
+    private static class MockCachedRepository extends MockResponder implements CachedRepository {
+
+        public InputStream checkout(boolean fail) throws IOException {
+            handleRequest("checkout", fail);
+            return (InputStream) handleResponse();
+        }
+
+        public boolean commit() throws IOException {
+            handleRequest("commit");
+            return false;
+        }
+
+        public InputStream getLocal(boolean fail) throws IOException {
+            return null;
+        }
+
+        public long getMostRecentVersion() {
+            return 0;
+        }
+
+        public boolean isCurrent() throws IOException {
+            return false;
+        }
+
+        public boolean revert() throws IOException {
+            return false;
+        }
+
+        public void writeLocal(InputStream data) throws IOException {
+            handleRequest("writeLocal", data);
+        }
+
+        public InputStream checkout(long version) throws IOException, IllegalArgumentException {
+            return null;
+        }
+
+        public boolean commit(InputStream data, long fromVersion) throws IOException, IllegalArgumentException {
+            return false;
+        }
+
+        public SortedRangeSet getRange() throws IOException {
+            return null;
+        }
+
+    }
+
+    /**
+     * Base class responder, used for inspecting calls and staging responses.
+     */
+    private static class MockResponder {
+        protected BlockingQueue<Object> m_responses = new LinkedBlockingQueue<Object>();
+        protected BlockingQueue<Object[]> m_requests = new LinkedBlockingQueue<Object[]>();
+
+        public void addResponse(Object response) {
+            m_responses.add(response);
+        }
+
+        public Object[] getRequest(boolean wait) {
+            if (wait) {
+                Object[] result = null;
+                try {
+                    result = m_requests.poll(5, TimeUnit.SECONDS);
+                }
+                catch (Exception e) {
+                    System.err.println("Interrupted while waiting for blocked queue.");
+                    Thread.currentThread().interrupt();
+                }
+                if (result == null) {
+                    assert false : "Even after 5 seconds, no request was ready for us.";
+                }
+                return result;
+            }
+            else {
+                return m_requests.poll();
+            }
+        }
+
+        public boolean moreRequests() {
+            return !m_requests.isEmpty();
+        }
+
+        protected void handleRequest(Object... objs) {
+            m_requests.add(objs);
+        }
+
+        protected Object handleResponse() {
+            return m_responses.poll();
+        }
+    }
+
+    /**
+     * Helper method that gets the contents of a stream into a single string.
+     */
+    private static String getInputStreamAsString(InputStream in) throws IOException {
+        char[] buf = new char[1];
+        StringBuilder found = new StringBuilder();
+        InputStreamReader bf = new InputStreamReader(in);
+        while (bf.read(buf) > 0) {
+            found.append(buf);
+        }
+        bf.close();
+        return found.toString();
+    }
+
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/client/repositoryuseradmin/impl/RepositoryUserAdminTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/client/repositoryuseradmin/impl/RepositoryUserAdminTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/client/repositoryuseradmin/impl/RepositoryUserAdminTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/client/repositoryuseradmin/impl/RepositoryUserAdminTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,139 @@
+package net.luminis.liq.client.repositoryuseradmin.impl;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+import net.luminis.liq.test.utils.TestUtils;
+
+import org.apache.felix.framework.FilterImpl;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.useradmin.Group;
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.User;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class RepositoryUserAdminTest {
+
+    private RepositoryUserAdminImpl m_impl;
+
+    @BeforeMethod(alwaysRun = true)
+    public void setUp() {
+        m_impl = new RepositoryUserAdminImpl();
+        TestUtils.configureObject(m_impl, BundleContext.class, TestUtils.createMockObjectAdapter(BundleContext.class, new Object() {
+            @SuppressWarnings("unused")
+            public Filter createFilter(String s) throws InvalidSyntaxException {
+                return new FilterImpl(s);
+            }
+        }));
+    }
+
+    /**
+     * Tests basic creation and membership of groups.
+     */
+    @Test(groups = { UNIT })
+    public void testCreation() {
+        User user = (User) m_impl.createRole("me", Role.USER);
+        Group group = (Group) m_impl.createRole("myGroup", Role.GROUP);
+        group.addMember(user);
+        assert group.getMembers().length == 1 : "We expect to find one member, not " + group.getMembers().length;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test(groups = { UNIT })
+    public void testUserProperties() {
+        User user = (User) m_impl.createRole("me", Role.USER);
+        user.getProperties().put("fullname", "Mr. M. Me");
+        assert m_impl.getUser("fullname", "Mr. M. Me").equals(user);
+
+        Group group = (Group) m_impl.createRole("theGroup", Role.GROUP);
+        assert m_impl.getUser("fullname", "Mr. M. Me").equals(user); // We should not find the group we just created
+
+        m_impl.removeRole("me");
+        assert m_impl.getUser("fullname", "Mr. M. Me") == null; // We should not find the group we just created
+    }
+
+    @Test(groups = { UNIT })
+    public void testGetRoles() throws InvalidSyntaxException {
+        User user = (User) m_impl.createRole("me", Role.USER);
+        user.getProperties().put("fullname", "Mr. M. Me");
+        Group group = (Group) m_impl.createRole("myGroup", Role.GROUP);
+        Role[] roles = m_impl.getRoles(null);
+        assert roles.length == 2;
+        roles = m_impl.getRoles("(fullname=Mr. M. Me)");
+        assert roles.length == 1;
+        roles = m_impl.getRoles("(fullname=Mr. U. Me)");
+        assert roles == null; // Spec requires us to return null in stead of an empty array
+    }
+
+    @Test(groups = { UNIT })
+    public void testCreateDoubleRole() throws InvalidSyntaxException {
+        User user = (User) m_impl.createRole("test", Role.USER);
+        Group group = (Group) m_impl.createRole("test", Role.GROUP);
+        assert group == null;
+        assert m_impl.getRole("test").equals(user);
+        assert m_impl.getRoles(null).length == 1;
+    }
+
+    @Test(groups = { UNIT })
+    public void testCredentials() throws InvalidSyntaxException {
+        User user = (User) m_impl.createRole("me", Role.USER);
+        user.getCredentials().put("password", "swordfish");
+        assert user.hasCredential("password", "swordfish");
+        assert !user.hasCredential("pet", "swordfish");
+        assert !user.hasCredential("password", "barracuda");
+    }
+
+    @Test(groups = { UNIT })
+    public void testStringOnlyDictionary() throws InvalidSyntaxException {
+        User user = (User) m_impl.createRole("me", Role.USER);
+        try {
+            user.getProperties().put("clearanceLevel", new Integer(5));
+            assert false : "Only String or byte[] values should be allowed.";
+        }
+        catch (IllegalArgumentException iae) {
+            // expected
+        }
+
+        try {
+            user.getProperties().put("clearanceLevel", '5');
+            assert false : "Only String or byte[] values should be allowed.";
+        }
+        catch (IllegalArgumentException iae) {
+            // expected
+        }
+
+        try {
+            user.getProperties().put("clearanceLevel", "5");
+        }
+        catch (IllegalArgumentException iae) {
+            assert false : "String values should be allowed.";
+        }
+
+        try {
+            user.getProperties().put("clearanceLevel", new byte[] {'5'});
+        }
+        catch (IllegalArgumentException iae) {
+            assert false : "byte[] values should be allowed.";
+        }
+
+        try {
+            user.getProperties().put(new String[] {"clearanceLevel"}, "5");
+            assert false : "String[] keys should not be allowed.";
+        }
+        catch (IllegalArgumentException iae) {
+            // expected
+        }
+
+        try {
+            user.getProperties().put(new byte[] {'c','l','e','a','r','a','n','c','e','L','e','v','e','l'}, "5");
+            assert false : "byte[] keys should not be allowed.";
+        }
+        catch (IllegalArgumentException iae) {
+            // expected
+        }
+}
+
+
+
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/configurator/ConfiguratorTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/configurator/ConfiguratorTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/configurator/ConfiguratorTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/configurator/ConfiguratorTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,282 @@
+package net.luminis.liq.configurator;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Dictionary;
+import java.util.Properties;
+
+import net.luminis.liq.test.utils.FileUtils;
+import net.luminis.liq.test.utils.TestUtils;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.log.LogService;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class ConfiguratorTest {
+
+    private Configurator m_configurator;
+    private File m_configDir;
+    private ConfigurationAdmin m_configAdmin;
+
+    @BeforeMethod(alwaysRun = true)
+    protected void setUp() throws Exception {
+        m_configAdmin = new MockConfigAdmin();
+
+        m_configDir = FileUtils.createTempFile(null);
+        m_configDir.mkdir();
+        m_configurator = new Configurator(m_configDir, 400);
+
+        TestUtils.configureObject(m_configurator, ConfigurationAdmin.class, m_configAdmin);
+        TestUtils.configureObject(m_configurator, LogService.class);
+        TestUtils.configureObject(m_configurator, BundleContext.class, TestUtils.createMockObjectAdapter(BundleContext.class, new Object() {
+            @SuppressWarnings("unused")
+            public String getProperty(String key) {
+                return "contextProp";
+            }
+        }));
+        m_configurator.start();
+    }
+
+
+    /**
+     * save the properties into a configuration file the configurator can read.
+     * The file is first created and then moved to make sure the configuration doesn't read an empty file
+     */
+    private void saveConfiguration(String servicePid, Properties configuration) {
+        saveConfiguration(servicePid, null, configuration);
+    }
+
+    /**
+     * save the properties into a configuration file stored in a directory reflecting the factory pid
+     */
+    private void saveConfiguration(String servicePid, String factoryPid, Properties configuration) {
+        OutputStream fileOutputStream = null;
+        File outFile = null;
+        try {
+            outFile = FileUtils.createTempFile(null);
+            fileOutputStream = new FileOutputStream(outFile);
+            configuration.store(fileOutputStream, null);
+        } catch (IOException ioe) {
+            // the test will fail, ignore this.
+        } finally {
+            if (fileOutputStream != null) {
+                try {
+                    fileOutputStream.close();
+                }
+                catch (IOException e) {
+                    // nothing we can do
+                }
+            }
+        }
+        if (outFile != null) {
+            if (factoryPid == null) {
+                outFile.renameTo(new File(m_configDir, servicePid+".cfg"));
+            }
+            else {
+                File file = new File(m_configDir, factoryPid);
+                file.mkdirs();
+                outFile.renameTo(new File(file, servicePid+".cfg"));
+            }
+        }
+    }
+
+    // remove a created configuration file
+    private void removeConfiguration(String servicePid) {
+        removeConfiguration(servicePid, null);
+    }
+
+    private void removeConfiguration(String servicePid, String factoryPid) {
+        if (factoryPid != null) {
+            new File(m_configDir, factoryPid + File.separator + servicePid + ".cfg").delete();
+        } else {
+            new File(m_configDir, servicePid + ".cfg").delete();
+        }
+    }
+
+    // set some standard properties for testing
+    private Properties createProperties() {
+        Properties props = new Properties();
+        props.put("test", "value1");
+        props.put("test2", "value2");
+        return props;
+    }
+
+    // add a configuration
+    @SuppressWarnings("unchecked")
+    @Test(groups = { UNIT })
+    public void testAddConfiguration() {
+        Properties initialConfiguration = createProperties();
+        saveConfiguration("test-add", initialConfiguration);
+
+        Dictionary configuration = getAndWaitForConfiguration(initialConfiguration);
+        assert configuration != null : "No configuration received from configurator";
+        assert configuration.equals(createProperties()) : "Configuration content is unexpected";
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test(groups = { UNIT })
+    public void testAddFactoryConfiguration() {
+        Properties props = createProperties();
+        saveConfiguration("test-add", "testFactory", props);
+
+        Dictionary configuration = getAndWaitForConfiguration(props);
+        assert configuration != null : "No configuration received from configurator";
+        assert "testFactory_test-add".equals(configuration.remove("factory.instance.pid")) : "Incorrect factory instance pid was added to the configuration";
+        assert configuration.equals(createProperties()) : "Configuration content is unexpected";
+    }
+
+    // remove a configuration
+    @SuppressWarnings("unchecked")
+    @Test(groups = { UNIT })
+    public void testRemoveFactoryConfiguration() {
+        Properties props = createProperties();
+        saveConfiguration("test-remove", "testFactory", props);
+        getAndWaitForConfiguration(props);
+
+        removeConfiguration("test-remove", "testFactory");
+
+        // after some processing time, we should get a message that the configuration is now removed.
+        long startTimeMillis = System.currentTimeMillis();
+        boolean isDeleted = false;
+        try {
+            while (!isDeleted && (System.currentTimeMillis() < startTimeMillis + 2000)) {
+                isDeleted = ((MockConfiguration) m_configAdmin.getConfiguration("")).isDeleted();
+                if (!isDeleted) {
+                    Thread.sleep(100);
+                }
+            }
+        } catch (InterruptedException ie) {
+            // not much we can do
+        }
+        catch (IOException e) {
+            // cannot come from our mock config admin
+        }
+        assert isDeleted : "The configuration is not removed as expected";
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test(groups = { UNIT })
+    public void testPropertySubstitution( ) {
+        Properties initialConfiguration = createProperties();
+        initialConfiguration.put("var", "value");
+        initialConfiguration.put("subst", "${var}");
+        saveConfiguration("test-subst", initialConfiguration);
+
+        Dictionary configuration = getAndWaitForConfiguration(initialConfiguration);
+        assert configuration != null : "No configuration received from configurator";
+        assert configuration.get("subst").equals(configuration.get("var")) : "Substitution failed";
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test(groups = { UNIT })
+    public void testPropertySubstitutionFromContext() {
+        Properties initialConfiguration = createProperties();
+        initialConfiguration.put("subst", "${var}");
+        saveConfiguration("test-subst", initialConfiguration);
+
+        Dictionary configuration = getAndWaitForConfiguration(initialConfiguration);
+        assert configuration != null : "No configuration received from configurator";
+        assert configuration.get("subst") != null : "Substitution failed";
+    }
+
+    // update a configuration
+    @SuppressWarnings("unchecked")
+    @Test(groups = { UNIT })
+    public void testChangeConfiguration() {
+        Properties initialConfiguration = createProperties();
+        saveConfiguration("test-change", initialConfiguration);
+
+        Dictionary configuration = getAndWaitForConfiguration(initialConfiguration);
+        assert configuration != null : "No configuration received from configurator";
+        assert configuration.equals(initialConfiguration) : "Configuration content not expected. Was expecting " + initialConfiguration.size() + " but got " + configuration.size();
+
+        initialConfiguration.put("anotherKey","anotherValue");
+        saveConfiguration("test-change", initialConfiguration);
+
+        // now the configuration should be updated
+        configuration = getAndWaitForConfiguration(initialConfiguration);
+        assert configuration != null : "No configuration received from configurator";
+        assert configuration.equals(initialConfiguration) : "Configuration content not expected. Was expecting " + initialConfiguration.size() + " but got " + configuration.size();
+    }
+
+    // remove a configuration
+    @SuppressWarnings("unchecked")
+    @Test(groups = { UNIT })
+    public void testRemoveConfiguration() {
+        Properties initialConfiguration = createProperties();
+        saveConfiguration("test-remove", initialConfiguration);
+
+        Dictionary configuration = getAndWaitForConfiguration(initialConfiguration);
+        assert configuration != null : "No configuration received from configurator";
+        assert configuration.equals(createProperties()) : "Configuration content is unexpected";
+
+        // ok, the configuration is done.
+        // now try to remove it.
+        removeConfiguration("test-remove");
+
+        // after some processing time, we should get a message that the configuration is now removed.
+        long startTimeMillis = System.currentTimeMillis();
+        boolean isDeleted = false;
+        try {
+            while (!isDeleted && (System.currentTimeMillis() < startTimeMillis + 2000)) {
+                isDeleted = ((MockConfiguration) m_configAdmin.getConfiguration("")).isDeleted();
+                if (!isDeleted) {
+                    Thread.sleep(100);
+                }
+            }
+        } catch (InterruptedException ie) {
+            // not much we can do
+        }
+        catch (IOException e) {
+            // cannot come from our mock config admin
+        }
+        assert isDeleted : "The configuration is not removed as expected";
+    }
+
+    /**
+     * Get the configuration and if it not available yet wait for it.
+     * If there is still no configuration after the wait time,
+     * null is returned.
+     */
+    @SuppressWarnings("unchecked")
+    public Dictionary getAndWaitForConfiguration(Dictionary expectedConfiguration) {
+        long startTimeMillis = System.currentTimeMillis();
+        // make sure we iterate at least once
+        Dictionary configuration = null;
+        try {
+            boolean success = false;
+            while (!success && (System.currentTimeMillis() < startTimeMillis + 2000)) {
+                configuration = m_configAdmin.getConfiguration("").getProperties();
+                if (configuration != null) {
+                    synchronized(configuration) {
+                        if (expectedConfiguration.equals(configuration)) {
+                            success = true;
+                        }
+                    }
+                }
+                if (!success) {
+                    Thread.sleep(100);
+                }
+            }
+        } catch (InterruptedException ie) {
+            // not much we can do
+        }
+        catch (IOException e) {
+            // cannot come from our mock config admin
+        }
+        return configuration;
+    }
+
+    @AfterMethod(alwaysRun = true)
+    public void tearDown() throws Exception {
+        m_configurator.stop();
+        FileUtils.removeDirectoryWithContent(m_configDir);
+    }
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/configurator/MockConfigAdmin.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/configurator/MockConfigAdmin.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/configurator/MockConfigAdmin.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/configurator/MockConfigAdmin.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,36 @@
+package net.luminis.liq.configurator;
+
+import java.io.IOException;
+
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+public class MockConfigAdmin implements ConfigurationAdmin {
+
+    private Configuration m_configuration = new MockConfiguration();
+
+    public Configuration createFactoryConfiguration(String arg0) throws IOException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Configuration createFactoryConfiguration(String arg0, String arg1) throws IOException {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public Configuration getConfiguration(String pid) throws IOException {
+        return m_configuration;
+    }
+
+    public Configuration getConfiguration(String arg0, String arg1) throws IOException {
+        // TODO Auto-generated method stub
+        return m_configuration;
+    }
+
+    public Configuration[] listConfigurations(String arg0) throws IOException, InvalidSyntaxException {
+        return new Configuration[] {m_configuration};
+    }
+
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/configurator/MockConfiguration.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/configurator/MockConfiguration.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/configurator/MockConfiguration.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/configurator/MockConfiguration.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,57 @@
+package net.luminis.liq.configurator;
+
+import java.io.IOException;
+import java.util.Dictionary;
+
+import org.osgi.service.cm.Configuration;
+
+public class MockConfiguration implements Configuration {
+
+    @SuppressWarnings("unchecked")
+    private Dictionary m_properties = null;
+    private boolean m_isDeleted = false;
+
+    public void delete() throws IOException {
+        m_isDeleted = true;
+    }
+
+    public String getBundleLocation() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public String getFactoryPid() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public String getPid() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @SuppressWarnings("unchecked")
+    public synchronized Dictionary getProperties() {
+        return m_properties;
+    }
+
+    public void setBundleLocation(String arg0) {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void update() throws IOException {
+        // TODO Auto-generated method stub
+
+    }
+
+    @SuppressWarnings("unchecked")
+    public synchronized void update(Dictionary newConfiguration) throws IOException {
+            m_properties = newConfiguration;
+    }
+
+    public boolean isDeleted() {
+        return m_isDeleted;
+    }
+
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/deployment/DeploymentTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/deployment/DeploymentTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/deployment/DeploymentTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/deployment/DeploymentTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,75 @@
+package net.luminis.liq.deployment;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+
+import java.io.InputStream;
+
+import net.luminis.liq.deployment.deploymentadmin.DeploymentAdminDeployer;
+import net.luminis.liq.test.utils.TestUtils;
+
+import org.osgi.framework.Version;
+import org.osgi.service.deploymentadmin.DeploymentAdmin;
+import org.osgi.service.deploymentadmin.DeploymentPackage;
+import org.osgi.service.log.LogService;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+public class DeploymentTest {
+
+    private DeploymentAdminDeployer m_deploymentAdminDeployer;
+    private DeploymentPackage m_mockDeploymentPackage;
+
+    private static final String MOCK_NAME = "MockName";
+    private static final Version MOCK_VERSION = new Version("0.1");
+
+    @BeforeTest(alwaysRun = true)
+    protected void setUp() throws Exception {
+        m_deploymentAdminDeployer = new DeploymentAdminDeployer();
+        TestUtils.configureObject(m_deploymentAdminDeployer, LogService.class);
+        Object mockDeploymentAdmin = TestUtils.createMockObjectAdapter(DeploymentAdmin.class, new MockDeploymentAdmin());
+        TestUtils.configureObject(m_deploymentAdminDeployer, DeploymentAdmin.class, mockDeploymentAdmin);
+        m_mockDeploymentPackage = TestUtils.createMockObjectAdapter(DeploymentPackage.class, new MockDeploymentPackage());
+    }
+
+    @Test(groups = { UNIT })
+    public void testDeployment() throws Exception {
+        Object deploymentPackage = m_deploymentAdminDeployer.install(null);
+        assert m_deploymentAdminDeployer.getName(deploymentPackage).equals(MOCK_NAME) : "Installation of mock deployment package failed";
+        assert m_deploymentAdminDeployer.getVersion(deploymentPackage).equals(MOCK_VERSION) : "Installation of mock deployment package failed";
+        assert ((DeploymentPackage) m_deploymentAdminDeployer.list()[0]).getName().equals(MOCK_NAME) : "List result does not match expected result";
+        boolean exceptionthrown = false;
+        try {
+            m_deploymentAdminDeployer.getName(new String("illegalargument"));
+        } catch (IllegalArgumentException iae) {
+            exceptionthrown = true;
+        }
+        assert exceptionthrown : "Illegal argument for getName() did not throw exception";
+        exceptionthrown = false;
+        try {
+            m_deploymentAdminDeployer.getVersion(new String("illegalargument"));
+        } catch (IllegalArgumentException iae) {
+            exceptionthrown = true;
+        }
+        assert exceptionthrown : "Illegal argument for getVersion() did not throw exception";
+    }
+
+    private class MockDeploymentAdmin {
+        public DeploymentPackage installDeploymentPackage(InputStream is) {
+            return m_mockDeploymentPackage;
+        }
+
+        public DeploymentPackage[] listDeploymentPackages() {
+            return new DeploymentPackage[] {m_mockDeploymentPackage};
+        }
+    }
+
+    private class MockDeploymentPackage {
+        public String getName() {
+            return MOCK_NAME;
+        }
+
+        public Version getVersion() {
+            return MOCK_VERSION;
+        }
+    }
+}