all connect calls are now validated.
authorerik <erik@77661180-640e-0410-b3a8-9f9b13e6d0e0>
Sun, 8 Jun 2008 11:57:23 +0000 (11:57 +0000)
committererik <erik@77661180-640e-0410-b3a8-9f9b13e6d0e0>
Sun, 8 Jun 2008 11:57:23 +0000 (11:57 +0000)
system/general/src/main/java/org/wamblee/system/container/Container.java
system/general/src/test/java/org/wamblee/system/container/ContainerTest.java

index e4466d4a3f5b972f6aab3d96c2e6bd510faf0013..d86ec1ceaa42ded130612eb9c4d8ae46ccbd8c99 100644 (file)
@@ -184,7 +184,26 @@ public class Container extends AbstractComponent<Scope> {
     
     public void connectExternalProvided(String aExternalProvided, String aComponent, String aProvidedInterface) {
         checkSealed();
-        // TODO validate
+        Component server = findComponent(aComponent);
+       
+      
+        if ( server == null ) { 
+               throw new SystemAssemblyException("No component '" + aComponent + "' in the container");
+        }
+        if ( aProvidedInterface != null ) { 
+               if ( findInterface(server.getProvidedInterfaces(), aProvidedInterface) == null) { 
+                       throw new SystemAssemblyException(
+                                       getQualifiedName() + ": Component '" + aComponent + "' does not have a provided interface named '" 
+                                       + aProvidedInterface + "'");
+               }
+        }
+        if ( aExternalProvided != null ) { 
+               if ( findInterface(getProvidedInterfaces(), aExternalProvided) == null) { 
+                       throw new SystemAssemblyException(
+                                       getQualifiedName() + ": Container does not have a provided interface named '" 
+                                       + aExternalProvided + "'");
+               }
+        }
         _edgeFilter.add(new ConnectExternalProvidedProvidedFilter(aExternalProvided, aComponent, aProvidedInterface));
     }
 
index f678638843fbacc8e41421bfe54600dd3a5b555b..e61c023ca0e35ae66908b04259a0d99bee520a28 100644 (file)
@@ -41,668 +41,717 @@ import org.wamblee.test.EventTracker;
 
 public class ContainerTest extends TestCase {
 
-    private EventTracker<String> _tracker;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        _tracker = new EventTracker<String>();
-    }
-
-    private static class MyMultiple implements Serializable, Runnable {
-        @Override
-        public void run() {
-            // Empty
-        }
-    }
-
-    private List<Pair<ProvidedInterface, Component>> createProvidedInput(
-            ProvidedInterface[] aProvided, Component aProvider) {
-        List<Pair<ProvidedInterface, Component>> result = new ArrayList<Pair<ProvidedInterface, Component>>();
-        for (ProvidedInterface provided : aProvided) {
-            result.add(new Pair<ProvidedInterface, Component>(provided,
-                    aProvider));
-        }
-        return result;
-    }
-
-    public void testEnvironmentApplication() {
-        Environment environment = new Environment(_tracker);
-        Application application = new Application(_tracker);
-        Container container = new Container("root", new Component[] {
-                environment, application }, new ProvidedInterface[0],
-                new RequiredInterface[0]);
-        Scope scope = container.start();
-        assertTrue(container.isSealed());
-        AssertionUtils.assertEquals(new String[] { "start.environment",
-                "start.application" }, _tracker.getEvents(
-                Thread.currentThread()).toArray(new String[0]));
-        assertEquals(0, scope.getProvidedInterfaces().size());
-
-        assertEquals(environment.getString(), application.getString());
-        assertEquals(environment.getInteger(), application.getInteger());
-
-    }
-
-    public void testEnvironmentApplicationSimpleConstructor() {
-        Environment environment = new Environment(_tracker);
-        Application application = new Application(_tracker);
-        Container container = new Container("root").addComponent(environment)
-                .addComponent(application);
-
-        Scope scope = container.start();
-        AssertionUtils.assertEquals(new String[] { "start.environment",
-                "start.application" }, _tracker.getEvents(
-                Thread.currentThread()).toArray(new String[0]));
-        assertEquals(0, scope.getProvidedInterfaces().size());
-
-        assertEquals(environment.getString(), application.getString());
-        assertEquals(environment.getInteger(), application.getInteger());
-
-    }
-
-    public void testApplicationEnvironment() {
-        try {
-            Component<?> environment = new Environment();
-            Component<?> application = new Application();
-            Container container = new Container("root", new Component[] {
-                    application, environment }, new ProvidedInterface[0],
-                    new RequiredInterface[0]);
-            container.start();
-        } catch (SystemAssemblyException e) {
-            // e.printStackTrace();
-            return;
-        }
-        fail();
-    }
-
-    public void testComposite() {
-        Component<?> environment = new Environment(_tracker);
-        Component<?> application = new Application(_tracker);
-        assertEquals(0, _tracker.getEventCount());
-
-        Container system = new Container("all", new Component[] { environment,
-                application }, new ProvidedInterface[0],
-                new RequiredInterface[0]);
-        Scope runtime = system.start();
-        List<RequiredInterface> required = system.getRequiredInterfaces();
-        assertEquals(0, required.size());
-        List<ProvidedInterface> provided = system.getProvidedInterfaces();
-        assertEquals(0, provided.size());
-
-        AssertionUtils.assertEquals(new String[] { "start.environment",
-                "start.application" }, _tracker.getEvents(
-                Thread.currentThread()).toArray(new String[0]));
-        _tracker.clear();
-
-        system.stop(runtime);
-        AssertionUtils.assertEquals(new String[] { "stop.application",
-                "stop.environment" }, _tracker
-                .getEvents(Thread.currentThread()).toArray(new String[0]));
-
-    }
-
-    public void testCompositeWithWrongProvidedInfo() {
-        try {
-            Component<?> environment = new Environment();
-            Component<?> application = new Application();
-            Container system = new Container("all", new Component[] {
-                    environment, application },
-                    new ProvidedInterface[] { new DefaultProvidedInterface(
-                            "float", Float.class) },
-                    new DefaultRequiredInterface[0]);
-            system.validate();
-        } catch (SystemAssemblyException e) {
-            return;
-        }
-        fail();
-    }
-
-    public void testCompositeRequiredInterfaceNotProvided() {
-        try {
-            Component<?> environment = new Environment();
-            Component<?> application = new Application();
-            Container system = new Container("all", new Component[] {
-                    environment, application }, new ProvidedInterface[0],
-                    new RequiredInterface[] { new DefaultRequiredInterface(
-                            "string", String.class) });
-            system.start();
-        } catch (SystemAssemblyException e) {
-            return;
-        }
-        fail();
-    }
-
-    public void testCompositeWithSuperfluousRequiredInfo() {
-        Component<?> environment = new Environment();
-        Component<?> application = new Application();
-        Container system = new Container("all", new Component[] { environment,
-                application }, new ProvidedInterface[0],
-                new RequiredInterface[] { new DefaultRequiredInterface("float",
-                        Float.class) });
-        system.getRequiredInterfaces().get(0)
-                .setProvider(new DefaultProvidedInterface("hallo", Float.class));
-        system.start();
-        List<RequiredInterface> required = system.getRequiredInterfaces();
-        assertEquals(1, required.size());
-        List<ProvidedInterface> provided = system.getProvidedInterfaces();
-        assertEquals(0, provided.size());
-    }
-
-    public void testCompositeWithExternalDependencesNotProvided() {
-        try {
-            Component<?> application = new Application();
-           
-            Container system = new Container("all",
-                    new Component[] { application }, new ProvidedInterface[0],
-                    application.getRequiredInterfaces().toArray(new RequiredInterface[0]));
-            system.start();
-        } catch (SystemAssemblyException e) {
-            return;
-        }
-        fail();
-    }
-
-    public void testDuplicateComponent() {
-        try {
-            Component<?> comp1 = new Application();
-            Component<?> comp2 = new Application();
-            Container system = new Container("top");
-            system.addComponent(comp1).addComponent(comp2);
-        } catch (SystemAssemblyException e) {
-            return;
-        }
-        fail();
-    }
-
-
-    public void testInconsistentHierarchy() {
-        try {
-            Component<?> comp = new Application();
-            Container system = new Container("top").addComponent(comp);
-            Container system2 = new Container("top2").addComponent(comp);
-        } catch (SystemAssemblyException e) {
-            return;
-        }
-        fail();
-    }
-
-    public void testCompositeWithExternalDependencesProvided() {
-
-        Component<?> environment = new Environment();
-        Component<?> application = new Application();
-        Container system = new Container("all",
-                new Component[] { application }, new ProvidedInterface[0],
-                application.getRequiredInterfaces().toArray(new RequiredInterface[0]));
-        environment.start(new DefaultScope(new ProvidedInterface[0]));
-        system.getRequiredInterfaces().get(0).setProvider(environment
-                .getProvidedInterfaces().get(0));
-        system.getRequiredInterfaces().get(1).setProvider(environment
-                .getProvidedInterfaces().get(1));
-
-        system.start();
-        List<RequiredInterface> required = system.getRequiredInterfaces();
-        assertEquals(2, required.size());
-        List<ProvidedInterface> provided = system.getProvidedInterfaces();
-        assertEquals(0, provided.size());
-
-    }
-
-    public void testAmbiguousInterfaces() {
-        try {
-            Component<?> environment1 = new Environment();
-            Component<?> environment2 = new Environment();
-            Component<?> application = new Application();
-            Container container = new Container("root", new Component[] {
-                    environment1, environment2, application },
-                    new ProvidedInterface[0], new RequiredInterface[0]);
-            container.start();
-
-        } catch (SystemAssemblyException e) {
-            return;
-        }
-        fail();
-    }
-
-    public void testIncompleteRequirements() {
-        try {
-            Component<?> application = new Application();
-            Container system = new Container("all",
-                    new Component[] { application }, new ProvidedInterface[0],
-                    new RequiredInterface[0]);
-            system.start();
-        } catch (SystemAssemblyException e) {
-            return;
-        }
-        fail();
-    }
-
-    public void testEnvironmentApplicationRollbackOnException()
-            throws Exception {
-        IMocksControl control = EasyMock.createStrictControl();
-
-        Environment environment = new Environment(_tracker);
-        Application application = control.createMock(Application.class,
-                new ConstructorArgs(Application.class.getConstructor()),
-                Application.class.getDeclaredMethod("doStart", Scope.class));
-
-        application.doStart(EasyMockMatchers.anyObject(Scope.class));
-        EasyMock.expectLastCall().andThrow(new RuntimeException());
-        control.replay();
-
-        try {
-            Container container = new Container("root", new Component[] {
-                    environment, application }, new ProvidedInterface[0],
-                    new RequiredInterface[0]);
-
-            container.start();
-        } catch (RuntimeException e) {
-            AssertionUtils.assertEquals(new String[] { "start.environment",
-                    "stop.environment" }, _tracker.getEvents(
-                    Thread.currentThread()).toArray(new String[0]));
-            return;
-        }
-        fail();
-    }
-
-    public void testEnvironmentApplicationRollbackOnExceptionWithExceptionOnStop()
-            throws Exception {
-        IMocksControl control = EasyMock.createControl();
-
-        Environment environment = new Environment(_tracker);
-        // Application 1 will throw an exception while stopping.
-        Application application1 = control.createMock(Application.class,
-                new ConstructorArgs(Application.class.getConstructor()),
-                Application.class.getDeclaredMethod("doStop", Object.class));
-
-        application1.doStop(EasyMock.anyObject());
-        EasyMock.expectLastCall().andThrow(new RuntimeException());
-
-        // application 2 will throw an exception while starting
-        Application application2 = control.createMock(Application.class,
-                new ConstructorArgs(Application.class
-                        .getConstructor(String.class), "application2"),
-                Application.class.getDeclaredMethod("doStart", Scope.class));
-
-        application2.doStart(EasyMockMatchers.anyObject(Scope.class));
-        EasyMock.expectLastCall().andThrow(new RuntimeException());
-
-        control.replay();
-
-        try {
-            Container container = new Container("root", new Component[] {
-                    environment, application1, application2 },
-                    new ProvidedInterface[0], new RequiredInterface[0]);
-
-            container.start();
-        } catch (RuntimeException e) {
-            AssertionUtils.assertEquals(new String[] { "start.environment",
-                    "stop.environment" }, _tracker.getEvents(
-                    Thread.currentThread()).toArray(new String[0]));
-            return;
-        }
-        fail();
-    }
-
-    public void testOptionalRequiredInterfaceProvidedOptionalInternal() {
-        Application application = new Application(true);
-        Container container = new Container("top",
-                new Component[] { application }, new ProvidedInterface[0],
-                Application.required(true));
-        Environment env = new Environment();
-        container.getRequiredInterfaces().get(0).setProvider(env
-                .getProvidedInterfaces().get(0));
-        container.getRequiredInterfaces().get(1).setProvider(env
-                .getProvidedInterfaces().get(1));
-        Scope external = new DefaultScope(env.getProvidedInterfaces());
-        env.start(external);
-
-        container.start(external);
-        assertSame(env.getProvidedInterfaces().get(0), container
-                .getRequiredInterfaces().get(0).getProvider());
-        assertSame(env.getProvidedInterfaces().get(1), container
-                .getRequiredInterfaces().get(1).getProvider());
-        assertSame(env.getProvidedInterfaces().get(0), application
-                .getRequiredInterfaces().get(0).getProvider());
-        assertSame(env.getProvidedInterfaces().get(1), application
-                .getRequiredInterfaces().get(1).getProvider());
-    }
-
-    public void testOptionalRequiredInterfaceNotProvidedOptionalInternal() {
-        Application application = new Application(true);
-        Container container = new Container("top",
-                new Component[] { application }, new ProvidedInterface[0],
-                Application.required(true));
-        Environment env = new Environment();
-        container.getRequiredInterfaces().get(0).setProvider(env
-                .getProvidedInterfaces().get(0));
-        Scope external = new DefaultScope(new ProvidedInterface[0]);
-        external.publishInterface(env.getProvidedInterfaces().get(0), env
-                .getString());
-        container.start(external);
-        assertSame(env.getProvidedInterfaces().get(0), container
-                .getRequiredInterfaces().get(0).getProvider());
-        assertNull(container.getRequiredInterfaces().get(1).getProvider());
-        assertSame(env.getProvidedInterfaces().get(0), application
-                .getRequiredInterfaces().get(0).getProvider());
-        assertNull(application.getRequiredInterfaces().get(1).getProvider());
-    }
-
-    public void testOptionalRequiredInterfaceProvidedMandatoryInternal() {
-        Application application = new Application();
-        Container container = new Container("top",
-                new Component[] { application }, new ProvidedInterface[0],
-                Application.required(true));
-        Environment env = new Environment();
-        container.getRequiredInterfaces().get(0).setProvider(env
-                .getProvidedInterfaces().get(0));
-        container.getRequiredInterfaces().get(1).setProvider(env
-                .getProvidedInterfaces().get(1));
-        try {
-            container.start();
-        } catch (SystemAssemblyException e) {
-            return;
-        }
-        fail();
-    }
-
-    public void testSealed() {
-        final Container container = new Container("xx");
-        assertFalse(container.isSealed());
-        container.start();
-        assertTrue(container.isSealed());
-
-        AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
-            @Override
-            public void run() throws Exception {
-                container.addComponent(new Application());
-            }
-        }, SystemAssemblyException.class);
-
-        AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
-            @Override
-            public void run() throws Exception {
-                container.connectRequiredProvided("x", "y", "a", "b");
-            }
-        }, SystemAssemblyException.class);
-        AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
-            @Override
-            public void run() throws Exception {
-                container.connectExternalRequired("x", "y", "a");
-            }
-        }, SystemAssemblyException.class);
-        AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
-            @Override
-            public void run() throws Exception {
-                container.connectExternalProvided("x", "y", "z");
-            }
-        }, SystemAssemblyException.class);
-        AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
-            @Override
-            public void run() throws Exception {
-                container.addProvidedInterface(new DefaultProvidedInterface(
-                        "xx", String.class));
-            }
-        }, SystemAssemblyException.class);
-
-        AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
-            @Override
-            public void run() throws Exception {
-                container.addRequiredInterface(new DefaultRequiredInterface(
-                        "xx", String.class));
-            }
-        }, SystemAssemblyException.class);
-    }
-
-    public void testRestriction() {
-        Environment env1 = new Environment("env1");
-        Environment env2 = new Environment("env2");
-        Application app = new Application("app");
-        Container container = new Container("top").addComponent(env1)
-                .addComponent(env2).addComponent(app);
-        container.connectRequiredProvided("app", null, "env1", null);
-        container.start();
-        assertEquals(env1.getString(), app.getString());
-        assertEquals(env1.getInteger(), app.getInteger());
-        assertFalse(env2.getString().equals(app.getString()));
-        assertFalse(env2.getInteger().equals(app.getInteger()));
-    }
-    
-    public void testRestrictionWithFromAndToInterfaceName() {
-        Environment env1 = new Environment("env1");
-        Environment env2 = new Environment("env2");
-        Application app = new Application("app");
-        Container container = new Container("top").addComponent(env1)
-                .addComponent(env2).addComponent(app);
-        container.connectRequiredProvided("app", app.getRequiredInterfaces().get(0).getName(), 
-                       "env1", env1.getProvidedInterfaces().get(0).getName());
-        container.connectRequiredProvided("app", app.getRequiredInterfaces().get(1).getName(), 
-                       "env2", env2.getProvidedInterfaces().get(1).getName());
-        container.start();
-        assertEquals(env1.getString(), app.getString());
-        assertEquals(env2.getInteger(), app.getInteger());
-        assertFalse(env2.getString().equals(app.getString()));
-        assertFalse(env1.getInteger().equals(app.getInteger()));
-    }
-    
-    public void testRestrictionWrongComponentNames() {
-        Environment env1 = new Environment("env1");
-        Environment env2 = new Environment("env2");
-        Application app = new Application("app");
-        final Container container = new Container("top").addComponent(env1)
-                .addComponent(env2).addComponent(app);
-        AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { 
-               @Override
-               public void run() throws Exception {
-                       container.connectRequiredProvided("app2", null, "env1", null);
-               }
-        }, SystemAssemblyException.class); 
-        AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { 
-               @Override
-               public void run() throws Exception {
-                       container.connectRequiredProvided("app", null, "env3", null);
-               }
-        }, SystemAssemblyException.class); 
-    }
-    
-    public void testRestrictionWrongInterfaceNames() {
-        final Environment env1 = new Environment("env1");
-        Environment env2 = new Environment("env2");
-        final Application app = new Application("app");
-        final Container container = new Container("top").addComponent(env1)
-                .addComponent(env2).addComponent(app);
-        AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { 
-               @Override
-               public void run() throws Exception {
-                       container.connectRequiredProvided("app", 
-                                       app.getRequiredInterfaces().get(0).getName() + "xxx", "env1", null);
-               }
-        }, SystemAssemblyException.class); 
-        AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { 
-               @Override
-               public void run() throws Exception {
-                       container.connectRequiredProvided("app", null, "env1", 
-                                       env1.getProvidedInterfaces().get(0).getName() + "yyy");
-               }
-        }, SystemAssemblyException.class); 
-    }
-
-
-    public void testProvidedInDifferentScopes() {
-        // Scoping problem occurred. Externally and internally provided
-        // components clashed
-        // because unique id generation in the scope was wrong.
-
-        StringComponent str = new StringComponent("string");
-        Application app = new Application("app");
-        Container container = new Container("top").addComponent(str)
-                .addComponent(app);
-        container.addRequiredInterface(new DefaultRequiredInterface("integer",
-                Integer.class));
-
-        ProvidedInterface provided = new DefaultProvidedInterface("hallo",
-                Integer.class);
-        container.getRequiredInterfaces().get(0).setProvider(provided);
-
-        Scope external = new DefaultScope(new ProvidedInterface[0]);
-        external.publishInterface(provided, 100);
-        Scope scope = container.start(external);
-    }
-
-    public void testProvidedInterfaces() {
-        Environment env = new Environment(_tracker);
-        Container envcontainer = new Container("0").addComponent(env)
-                .addProvidedInterface(
-                        new DefaultProvidedInterface("string", String.class))
-                .addProvidedInterface(
-                        new DefaultProvidedInterface("integer", Integer.class));
-        Scope scope = envcontainer.start();
-
-        AssertionUtils.assertEquals(new String[] { "start.environment" },
-                _tracker.getEvents(Thread.currentThread()).toArray(
-                        new String[0]));
-
-        envcontainer.stop(scope);
-    }
-
-    public void testCoupleTwoContainers() {
-        Environment env = new Environment(_tracker);
-        Container envcontainer = new Container("0").addComponent(env)
-                .addProvidedInterface(
-                        new DefaultProvidedInterface("string", String.class))
-                .addProvidedInterface(
-                        new DefaultProvidedInterface("integer", Integer.class));
-
-        Application app = new Application(_tracker);
-        Container appcontainer = new Container("1").addComponent(app)
-                .addRequiredInterface(
-                        new DefaultRequiredInterface("string", String.class))
-                .addRequiredInterface(
-                        new DefaultRequiredInterface("integer", Integer.class));
-
-        Container top = new Container("top");
-        top.addComponent(envcontainer).addComponent(appcontainer);
-
-        top.start();
-        AssertionUtils.assertEquals(new String[] { "start.environment",
-                "start.application" }, _tracker.getEvents(
-                Thread.currentThread()).toArray(new String[0]));
-
-    }
-
-    public void testNonUniqueRequiredInterface() {
-        final Container container = new Container("top");
-        container.addRequiredInterface(new DefaultRequiredInterface("i",
-                Integer.class));
-        container.addRequiredInterface(new DefaultRequiredInterface("x",
-                String.class));
-        container.addRequiredInterface(new DefaultRequiredInterface("y",
-                String.class));
-
-        Application app = new Application("1");
-        container.addComponent(app);
-
-        AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
-            @Override
-            public void run() throws Exception {
-                container.start();
-            }
-        }, SystemAssemblyException.class);
-
-        container.connectExternalRequired("1", app.getRequiredInterfaces().get(0)
-                .getName(), "y");
-
-        ProvidedInterface i = new DefaultProvidedInterface("i", Integer.class);
-        ProvidedInterface x = new DefaultProvidedInterface("x", String.class);
-        ProvidedInterface y = new DefaultProvidedInterface("y", String.class);
-
-        Scope externalScope = new DefaultScope(new ProvidedInterface[0]);
-
-        externalScope.publishInterface(i, 100);
-        externalScope.publishInterface(x, "x-value");
-        externalScope.publishInterface(y, "y-value");
-
-        container.getRequiredInterfaces().get(0).setProvider(i);
-        container.getRequiredInterfaces().get(1).setProvider(x);
-        container.getRequiredInterfaces().get(2).setProvider(y);
-
-        Scope runtime = container.start(externalScope);
-
-        assertEquals("y-value", app.getString());
-
-    }
-    
-    public void testNonUniqueRequiredInterfaceWrongNames() {
-        final Container container = new Container("top");
-        container.addRequiredInterface(new DefaultRequiredInterface("i",
-                Integer.class));
-        container.addRequiredInterface(new DefaultRequiredInterface("x",
-                String.class));
-        container.addRequiredInterface(new DefaultRequiredInterface("y",
-                String.class));
-
-        final Application app = new Application("1");
-        container.addComponent(app);
-        
-        // wrong component name. 
-        AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
-               @Override
-               public void run() throws Exception {
-                       container.connectExternalRequired("2", "x", "y"); 
-               }
-        }, SystemAssemblyException.class);
-        
-        // Wrong interface name of component.
-        AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
-               @Override
-               public void run() throws Exception {
-                       container.connectExternalRequired("1", 
-                                       app.getRequiredInterfaces().get(0).getName() + "xxx", "y"); 
-               }
-        }, SystemAssemblyException.class);
-        
-        // Wrong external interface name of container
-        AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
-               @Override
-               public void run() throws Exception {
-                       container.connectExternalRequired("1", 
-                                       app.getRequiredInterfaces().get(0).getName(), "z"); 
-               }
-        }, SystemAssemblyException.class);
-    }
-
-    public void testNonUniqueProvidedInterface() {
-
-        final Container container = new Container("top")
-                .addProvidedInterface(new DefaultProvidedInterface("external",
-                        String.class));
-        Environment env1 = new Environment("env1");
-        Environment env2 = new Environment("env2");
-
-        container.addComponent(env1);
-        container.addComponent(env2);
-
-        AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
-            @Override
-            public void run() throws Exception {
-                container.start();
-            }
-        }, SystemAssemblyException.class);
-
-        // now choose env2
-
-        container.connectExternalProvided(container.getProvidedInterfaces().get(0)
-                .getName(), env2.getName(), env2.getProvidedInterfaces().get(0)
-                .getName());
-
-        Scope scope = container.start();
-
-        // check the value of the provided interface of the container
-
-        String value = scope.getInterfaceImplementation(container
-                .getProvidedInterfaces().get(0), String.class);
-        assertNotNull(value);
-        assertEquals(value, env2.getString());
-        assertFalse(value.equals(env1.getString()));
-    }
+       private EventTracker<String> _tracker;
+
+       @Override
+       protected void setUp() throws Exception {
+               super.setUp();
+               _tracker = new EventTracker<String>();
+       }
+
+       private static class MyMultiple implements Serializable, Runnable {
+               @Override
+               public void run() {
+                       // Empty
+               }
+       }
+
+       private List<Pair<ProvidedInterface, Component>> createProvidedInput(
+                       ProvidedInterface[] aProvided, Component aProvider) {
+               List<Pair<ProvidedInterface, Component>> result = new ArrayList<Pair<ProvidedInterface, Component>>();
+               for (ProvidedInterface provided : aProvided) {
+                       result.add(new Pair<ProvidedInterface, Component>(provided,
+                                       aProvider));
+               }
+               return result;
+       }
+
+       public void testEnvironmentApplication() {
+               Environment environment = new Environment(_tracker);
+               Application application = new Application(_tracker);
+               Container container = new Container("root", new Component[] {
+                               environment, application }, new ProvidedInterface[0],
+                               new RequiredInterface[0]);
+               Scope scope = container.start();
+               assertTrue(container.isSealed());
+               AssertionUtils.assertEquals(new String[] { "start.environment",
+                               "start.application" }, _tracker.getEvents(
+                               Thread.currentThread()).toArray(new String[0]));
+               assertEquals(0, scope.getProvidedInterfaces().size());
+
+               assertEquals(environment.getString(), application.getString());
+               assertEquals(environment.getInteger(), application.getInteger());
+
+       }
+
+       public void testEnvironmentApplicationSimpleConstructor() {
+               Environment environment = new Environment(_tracker);
+               Application application = new Application(_tracker);
+               Container container = new Container("root").addComponent(environment)
+                               .addComponent(application);
+
+               Scope scope = container.start();
+               AssertionUtils.assertEquals(new String[] { "start.environment",
+                               "start.application" }, _tracker.getEvents(
+                               Thread.currentThread()).toArray(new String[0]));
+               assertEquals(0, scope.getProvidedInterfaces().size());
+
+               assertEquals(environment.getString(), application.getString());
+               assertEquals(environment.getInteger(), application.getInteger());
+
+       }
+
+       public void testApplicationEnvironment() {
+               try {
+                       Component<?> environment = new Environment();
+                       Component<?> application = new Application();
+                       Container container = new Container("root", new Component[] {
+                                       application, environment }, new ProvidedInterface[0],
+                                       new RequiredInterface[0]);
+                       container.start();
+               } catch (SystemAssemblyException e) {
+                       // e.printStackTrace();
+                       return;
+               }
+               fail();
+       }
+
+       public void testComposite() {
+               Component<?> environment = new Environment(_tracker);
+               Component<?> application = new Application(_tracker);
+               assertEquals(0, _tracker.getEventCount());
+
+               Container system = new Container("all", new Component[] { environment,
+                               application }, new ProvidedInterface[0],
+                               new RequiredInterface[0]);
+               Scope runtime = system.start();
+               List<RequiredInterface> required = system.getRequiredInterfaces();
+               assertEquals(0, required.size());
+               List<ProvidedInterface> provided = system.getProvidedInterfaces();
+               assertEquals(0, provided.size());
+
+               AssertionUtils.assertEquals(new String[] { "start.environment",
+                               "start.application" }, _tracker.getEvents(
+                               Thread.currentThread()).toArray(new String[0]));
+               _tracker.clear();
+
+               system.stop(runtime);
+               AssertionUtils.assertEquals(new String[] { "stop.application",
+                               "stop.environment" }, _tracker
+                               .getEvents(Thread.currentThread()).toArray(new String[0]));
+
+       }
+
+       public void testCompositeWithWrongProvidedInfo() {
+               try {
+                       Component<?> environment = new Environment();
+                       Component<?> application = new Application();
+                       Container system = new Container("all", new Component[] {
+                                       environment, application },
+                                       new ProvidedInterface[] { new DefaultProvidedInterface(
+                                                       "float", Float.class) },
+                                       new DefaultRequiredInterface[0]);
+                       system.validate();
+               } catch (SystemAssemblyException e) {
+                       return;
+               }
+               fail();
+       }
+
+       public void testCompositeRequiredInterfaceNotProvided() {
+               try {
+                       Component<?> environment = new Environment();
+                       Component<?> application = new Application();
+                       Container system = new Container("all", new Component[] {
+                                       environment, application }, new ProvidedInterface[0],
+                                       new RequiredInterface[] { new DefaultRequiredInterface(
+                                                       "string", String.class) });
+                       system.start();
+               } catch (SystemAssemblyException e) {
+                       return;
+               }
+               fail();
+       }
+
+       public void testCompositeWithSuperfluousRequiredInfo() {
+               Component<?> environment = new Environment();
+               Component<?> application = new Application();
+               Container system = new Container("all", new Component[] { environment,
+                               application }, new ProvidedInterface[0],
+                               new RequiredInterface[] { new DefaultRequiredInterface("float",
+                                               Float.class) });
+               system.getRequiredInterfaces().get(0).setProvider(
+                               new DefaultProvidedInterface("hallo", Float.class));
+               system.start();
+               List<RequiredInterface> required = system.getRequiredInterfaces();
+               assertEquals(1, required.size());
+               List<ProvidedInterface> provided = system.getProvidedInterfaces();
+               assertEquals(0, provided.size());
+       }
+
+       public void testCompositeWithExternalDependencesNotProvided() {
+               try {
+                       Component<?> application = new Application();
+
+                       Container system = new Container("all",
+                                       new Component[] { application }, new ProvidedInterface[0],
+                                       application.getRequiredInterfaces().toArray(
+                                                       new RequiredInterface[0]));
+                       system.start();
+               } catch (SystemAssemblyException e) {
+                       return;
+               }
+               fail();
+       }
+
+       public void testDuplicateComponent() {
+               try {
+                       Component<?> comp1 = new Application();
+                       Component<?> comp2 = new Application();
+                       Container system = new Container("top");
+                       system.addComponent(comp1).addComponent(comp2);
+               } catch (SystemAssemblyException e) {
+                       return;
+               }
+               fail();
+       }
+
+       public void testInconsistentHierarchy() {
+               try {
+                       Component<?> comp = new Application();
+                       Container system = new Container("top").addComponent(comp);
+                       Container system2 = new Container("top2").addComponent(comp);
+               } catch (SystemAssemblyException e) {
+                       return;
+               }
+               fail();
+       }
+
+       public void testCompositeWithExternalDependencesProvided() {
+
+               Component<?> environment = new Environment();
+               Component<?> application = new Application();
+               Container system = new Container("all",
+                               new Component[] { application }, new ProvidedInterface[0],
+                               application.getRequiredInterfaces().toArray(
+                                               new RequiredInterface[0]));
+               environment.start(new DefaultScope(new ProvidedInterface[0]));
+               system.getRequiredInterfaces().get(0).setProvider(
+                               environment.getProvidedInterfaces().get(0));
+               system.getRequiredInterfaces().get(1).setProvider(
+                               environment.getProvidedInterfaces().get(1));
+
+               system.start();
+               List<RequiredInterface> required = system.getRequiredInterfaces();
+               assertEquals(2, required.size());
+               List<ProvidedInterface> provided = system.getProvidedInterfaces();
+               assertEquals(0, provided.size());
+
+       }
+
+       public void testAmbiguousInterfaces() {
+               try {
+                       Component<?> environment1 = new Environment();
+                       Component<?> environment2 = new Environment();
+                       Component<?> application = new Application();
+                       Container container = new Container("root", new Component[] {
+                                       environment1, environment2, application },
+                                       new ProvidedInterface[0], new RequiredInterface[0]);
+                       container.start();
+
+               } catch (SystemAssemblyException e) {
+                       return;
+               }
+               fail();
+       }
+
+       public void testIncompleteRequirements() {
+               try {
+                       Component<?> application = new Application();
+                       Container system = new Container("all",
+                                       new Component[] { application }, new ProvidedInterface[0],
+                                       new RequiredInterface[0]);
+                       system.start();
+               } catch (SystemAssemblyException e) {
+                       return;
+               }
+               fail();
+       }
+
+       public void testEnvironmentApplicationRollbackOnException()
+                       throws Exception {
+               IMocksControl control = EasyMock.createStrictControl();
+
+               Environment environment = new Environment(_tracker);
+               Application application = control.createMock(Application.class,
+                               new ConstructorArgs(Application.class.getConstructor()),
+                               Application.class.getDeclaredMethod("doStart", Scope.class));
+
+               application.doStart(EasyMockMatchers.anyObject(Scope.class));
+               EasyMock.expectLastCall().andThrow(new RuntimeException());
+               control.replay();
+
+               try {
+                       Container container = new Container("root", new Component[] {
+                                       environment, application }, new ProvidedInterface[0],
+                                       new RequiredInterface[0]);
+
+                       container.start();
+               } catch (RuntimeException e) {
+                       AssertionUtils.assertEquals(new String[] { "start.environment",
+                                       "stop.environment" }, _tracker.getEvents(
+                                       Thread.currentThread()).toArray(new String[0]));
+                       return;
+               }
+               fail();
+       }
+
+       public void testEnvironmentApplicationRollbackOnExceptionWithExceptionOnStop()
+                       throws Exception {
+               IMocksControl control = EasyMock.createControl();
+
+               Environment environment = new Environment(_tracker);
+               // Application 1 will throw an exception while stopping.
+               Application application1 = control.createMock(Application.class,
+                               new ConstructorArgs(Application.class.getConstructor()),
+                               Application.class.getDeclaredMethod("doStop", Object.class));
+
+               application1.doStop(EasyMock.anyObject());
+               EasyMock.expectLastCall().andThrow(new RuntimeException());
+
+               // application 2 will throw an exception while starting
+               Application application2 = control.createMock(Application.class,
+                               new ConstructorArgs(Application.class
+                                               .getConstructor(String.class), "application2"),
+                               Application.class.getDeclaredMethod("doStart", Scope.class));
+
+               application2.doStart(EasyMockMatchers.anyObject(Scope.class));
+               EasyMock.expectLastCall().andThrow(new RuntimeException());
+
+               control.replay();
+
+               try {
+                       Container container = new Container("root", new Component[] {
+                                       environment, application1, application2 },
+                                       new ProvidedInterface[0], new RequiredInterface[0]);
+
+                       container.start();
+               } catch (RuntimeException e) {
+                       AssertionUtils.assertEquals(new String[] { "start.environment",
+                                       "stop.environment" }, _tracker.getEvents(
+                                       Thread.currentThread()).toArray(new String[0]));
+                       return;
+               }
+               fail();
+       }
+
+       public void testOptionalRequiredInterfaceProvidedOptionalInternal() {
+               Application application = new Application(true);
+               Container container = new Container("top",
+                               new Component[] { application }, new ProvidedInterface[0],
+                               Application.required(true));
+               Environment env = new Environment();
+               container.getRequiredInterfaces().get(0).setProvider(
+                               env.getProvidedInterfaces().get(0));
+               container.getRequiredInterfaces().get(1).setProvider(
+                               env.getProvidedInterfaces().get(1));
+               Scope external = new DefaultScope(env.getProvidedInterfaces());
+               env.start(external);
+
+               container.start(external);
+               assertSame(env.getProvidedInterfaces().get(0), container
+                               .getRequiredInterfaces().get(0).getProvider());
+               assertSame(env.getProvidedInterfaces().get(1), container
+                               .getRequiredInterfaces().get(1).getProvider());
+               assertSame(env.getProvidedInterfaces().get(0), application
+                               .getRequiredInterfaces().get(0).getProvider());
+               assertSame(env.getProvidedInterfaces().get(1), application
+                               .getRequiredInterfaces().get(1).getProvider());
+       }
+
+       public void testOptionalRequiredInterfaceNotProvidedOptionalInternal() {
+               Application application = new Application(true);
+               Container container = new Container("top",
+                               new Component[] { application }, new ProvidedInterface[0],
+                               Application.required(true));
+               Environment env = new Environment();
+               container.getRequiredInterfaces().get(0).setProvider(
+                               env.getProvidedInterfaces().get(0));
+               Scope external = new DefaultScope(new ProvidedInterface[0]);
+               external.publishInterface(env.getProvidedInterfaces().get(0), env
+                               .getString());
+               container.start(external);
+               assertSame(env.getProvidedInterfaces().get(0), container
+                               .getRequiredInterfaces().get(0).getProvider());
+               assertNull(container.getRequiredInterfaces().get(1).getProvider());
+               assertSame(env.getProvidedInterfaces().get(0), application
+                               .getRequiredInterfaces().get(0).getProvider());
+               assertNull(application.getRequiredInterfaces().get(1).getProvider());
+       }
+
+       public void testOptionalRequiredInterfaceProvidedMandatoryInternal() {
+               Application application = new Application();
+               Container container = new Container("top",
+                               new Component[] { application }, new ProvidedInterface[0],
+                               Application.required(true));
+               Environment env = new Environment();
+               container.getRequiredInterfaces().get(0).setProvider(
+                               env.getProvidedInterfaces().get(0));
+               container.getRequiredInterfaces().get(1).setProvider(
+                               env.getProvidedInterfaces().get(1));
+               try {
+                       container.start();
+               } catch (SystemAssemblyException e) {
+                       return;
+               }
+               fail();
+       }
+
+       public void testSealed() {
+               final Container container = new Container("xx");
+               assertFalse(container.isSealed());
+               container.start();
+               assertTrue(container.isSealed());
+
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               container.addComponent(new Application());
+                       }
+               }, SystemAssemblyException.class);
+
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               container.connectRequiredProvided("x", "y", "a", "b");
+                       }
+               }, SystemAssemblyException.class);
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               container.connectExternalRequired("x", "y", "a");
+                       }
+               }, SystemAssemblyException.class);
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               container.connectExternalProvided("x", "y", "z");
+                       }
+               }, SystemAssemblyException.class);
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               container.addProvidedInterface(new DefaultProvidedInterface(
+                                               "xx", String.class));
+                       }
+               }, SystemAssemblyException.class);
+
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               container.addRequiredInterface(new DefaultRequiredInterface(
+                                               "xx", String.class));
+                       }
+               }, SystemAssemblyException.class);
+       }
+
+       public void testRestriction() {
+               Environment env1 = new Environment("env1");
+               Environment env2 = new Environment("env2");
+               Application app = new Application("app");
+               Container container = new Container("top").addComponent(env1)
+                               .addComponent(env2).addComponent(app);
+               container.connectRequiredProvided("app", null, "env1", null);
+               container.start();
+               assertEquals(env1.getString(), app.getString());
+               assertEquals(env1.getInteger(), app.getInteger());
+               assertFalse(env2.getString().equals(app.getString()));
+               assertFalse(env2.getInteger().equals(app.getInteger()));
+       }
+
+       public void testRestrictionWithFromAndToInterfaceName() {
+               Environment env1 = new Environment("env1");
+               Environment env2 = new Environment("env2");
+               Application app = new Application("app");
+               Container container = new Container("top").addComponent(env1)
+                               .addComponent(env2).addComponent(app);
+               container.connectRequiredProvided("app", app.getRequiredInterfaces()
+                               .get(0).getName(), "env1", env1.getProvidedInterfaces().get(0)
+                               .getName());
+               container.connectRequiredProvided("app", app.getRequiredInterfaces()
+                               .get(1).getName(), "env2", env2.getProvidedInterfaces().get(1)
+                               .getName());
+               container.start();
+               assertEquals(env1.getString(), app.getString());
+               assertEquals(env2.getInteger(), app.getInteger());
+               assertFalse(env2.getString().equals(app.getString()));
+               assertFalse(env1.getInteger().equals(app.getInteger()));
+       }
+
+       public void testRestrictionWrongComponentNames() {
+               Environment env1 = new Environment("env1");
+               Environment env2 = new Environment("env2");
+               Application app = new Application("app");
+               final Container container = new Container("top").addComponent(env1)
+                               .addComponent(env2).addComponent(app);
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               container.connectRequiredProvided("app2", null, "env1", null);
+                       }
+               }, SystemAssemblyException.class);
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               container.connectRequiredProvided("app", null, "env3", null);
+                       }
+               }, SystemAssemblyException.class);
+       }
+
+       public void testRestrictionWrongInterfaceNames() {
+               final Environment env1 = new Environment("env1");
+               Environment env2 = new Environment("env2");
+               final Application app = new Application("app");
+               final Container container = new Container("top").addComponent(env1)
+                               .addComponent(env2).addComponent(app);
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               container.connectRequiredProvided("app", app
+                                               .getRequiredInterfaces().get(0).getName()
+                                               + "xxx", "env1", null);
+                       }
+               }, SystemAssemblyException.class);
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               container.connectRequiredProvided("app", null, "env1", env1
+                                               .getProvidedInterfaces().get(0).getName()
+                                               + "yyy");
+                       }
+               }, SystemAssemblyException.class);
+       }
+
+       public void testProvidedInDifferentScopes() {
+               // Scoping problem occurred. Externally and internally provided
+               // components clashed
+               // because unique id generation in the scope was wrong.
+
+               StringComponent str = new StringComponent("string");
+               Application app = new Application("app");
+               Container container = new Container("top").addComponent(str)
+                               .addComponent(app);
+               container.addRequiredInterface(new DefaultRequiredInterface("integer",
+                               Integer.class));
+
+               ProvidedInterface provided = new DefaultProvidedInterface("hallo",
+                               Integer.class);
+               container.getRequiredInterfaces().get(0).setProvider(provided);
+
+               Scope external = new DefaultScope(new ProvidedInterface[0]);
+               external.publishInterface(provided, 100);
+               Scope scope = container.start(external);
+       }
+
+       public void testProvidedInterfaces() {
+               Environment env = new Environment(_tracker);
+               Container envcontainer = new Container("0").addComponent(env)
+                               .addProvidedInterface(
+                                               new DefaultProvidedInterface("string", String.class))
+                               .addProvidedInterface(
+                                               new DefaultProvidedInterface("integer", Integer.class));
+               Scope scope = envcontainer.start();
+
+               AssertionUtils.assertEquals(new String[] { "start.environment" },
+                               _tracker.getEvents(Thread.currentThread()).toArray(
+                                               new String[0]));
+
+               envcontainer.stop(scope);
+       }
+
+       public void testCoupleTwoContainers() {
+               Environment env = new Environment(_tracker);
+               Container envcontainer = new Container("0").addComponent(env)
+                               .addProvidedInterface(
+                                               new DefaultProvidedInterface("string", String.class))
+                               .addProvidedInterface(
+                                               new DefaultProvidedInterface("integer", Integer.class));
+
+               Application app = new Application(_tracker);
+               Container appcontainer = new Container("1").addComponent(app)
+                               .addRequiredInterface(
+                                               new DefaultRequiredInterface("string", String.class))
+                               .addRequiredInterface(
+                                               new DefaultRequiredInterface("integer", Integer.class));
+
+               Container top = new Container("top");
+               top.addComponent(envcontainer).addComponent(appcontainer);
+
+               top.start();
+               AssertionUtils.assertEquals(new String[] { "start.environment",
+                               "start.application" }, _tracker.getEvents(
+                               Thread.currentThread()).toArray(new String[0]));
+
+       }
+
+       public void testNonUniqueRequiredInterface() {
+               final Container container = new Container("top");
+               container.addRequiredInterface(new DefaultRequiredInterface("i",
+                               Integer.class));
+               container.addRequiredInterface(new DefaultRequiredInterface("x",
+                               String.class));
+               container.addRequiredInterface(new DefaultRequiredInterface("y",
+                               String.class));
+
+               Application app = new Application("1");
+               container.addComponent(app);
+
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               container.start();
+                       }
+               }, SystemAssemblyException.class);
+
+               container.connectExternalRequired("1", app.getRequiredInterfaces().get(
+                               0).getName(), "y");
+
+               ProvidedInterface i = new DefaultProvidedInterface("i", Integer.class);
+               ProvidedInterface x = new DefaultProvidedInterface("x", String.class);
+               ProvidedInterface y = new DefaultProvidedInterface("y", String.class);
+
+               Scope externalScope = new DefaultScope(new ProvidedInterface[0]);
+
+               externalScope.publishInterface(i, 100);
+               externalScope.publishInterface(x, "x-value");
+               externalScope.publishInterface(y, "y-value");
+
+               container.getRequiredInterfaces().get(0).setProvider(i);
+               container.getRequiredInterfaces().get(1).setProvider(x);
+               container.getRequiredInterfaces().get(2).setProvider(y);
+
+               Scope runtime = container.start(externalScope);
+
+               assertEquals("y-value", app.getString());
+
+       }
+
+       public void testNonUniqueRequiredInterfaceWrongNames() {
+               final Container container = new Container("top");
+               container.addRequiredInterface(new DefaultRequiredInterface("i",
+                               Integer.class));
+               container.addRequiredInterface(new DefaultRequiredInterface("x",
+                               String.class));
+               container.addRequiredInterface(new DefaultRequiredInterface("y",
+                               String.class));
+
+               final Application app = new Application("1");
+               container.addComponent(app);
+
+               // wrong component name.
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               container.connectExternalRequired("2", "x", "y");
+                       }
+               }, SystemAssemblyException.class);
+
+               // Wrong interface name of component.
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               container.connectExternalRequired("1", app
+                                               .getRequiredInterfaces().get(0).getName()
+                                               + "xxx", "y");
+                       }
+               }, SystemAssemblyException.class);
+
+               // Wrong external interface name of container
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               container.connectExternalRequired("1", app
+                                               .getRequiredInterfaces().get(0).getName(), "z");
+                       }
+               }, SystemAssemblyException.class);
+       }
+
+       public void testNonUniqueProvidedInterface() {
+
+               final Container container = new Container("top")
+                               .addProvidedInterface(new DefaultProvidedInterface("external",
+                                               String.class));
+               Environment env1 = new Environment("env1");
+               Environment env2 = new Environment("env2");
+
+               container.addComponent(env1);
+               container.addComponent(env2);
+
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               container.start();
+                       }
+               }, SystemAssemblyException.class);
+
+               // now choose env2
+
+               container.connectExternalProvided(container.getProvidedInterfaces()
+                               .get(0).getName(), env2.getName(), env2.getProvidedInterfaces()
+                               .get(0).getName());
+
+               Scope scope = container.start();
+
+               // check the value of the provided interface of the container
+
+               String value = scope.getInterfaceImplementation(container
+                               .getProvidedInterfaces().get(0), String.class);
+               assertNotNull(value);
+               assertEquals(value, env2.getString());
+               assertFalse(value.equals(env1.getString()));
+       }
+
+       public void testNonUniqueProvidedInterfaceWrongNames() {
+
+               final Container container = new Container("top")
+                               .addProvidedInterface(new DefaultProvidedInterface("external",
+                                               String.class));
+               final Environment env1 = new Environment("env1");
+               final Environment env2 = new Environment("env2");
+
+               container.addComponent(env1);
+               container.addComponent(env2);
+
+               // Wrong external provided interface name
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               container.connectExternalProvided(container
+                                               .getProvidedInterfaces().get(0).getName()
+                                               + "xx", "env1", env1.getProvidedInterfaces().get(0)
+                                               .getName());
+                       }
+               }, SystemAssemblyException.class);
+
+               // Wrong provided interface name.
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               container.connectExternalProvided(container
+                                               .getProvidedInterfaces().get(0).getName(), "env1", env1
+                                               .getProvidedInterfaces().get(0).getName()
+                                               + "xx");
+                       }
+               }, SystemAssemblyException.class);
+
+               // Wrong provided component
+               AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
+                       @Override
+                       public void run() throws Exception {
+                               container.connectExternalProvided(container
+                                               .getProvidedInterfaces().get(0).getName(), "env3", env1
+                                               .getProvidedInterfaces().get(0).getName());
+                       }
+               }, SystemAssemblyException.class);
+       }
 }