From 1bec7da907a8bf9276e9faafa4a4da91309ad1a7 Mon Sep 17 00:00:00 2001 From: erik Date: Sat, 26 Apr 2008 20:22:02 +0000 Subject: [PATCH] Implemented restrictions on component connections in the Container. --- .../org/wamblee/system/core/Container.java | 60 +- .../system/core/DefaultProvidedInterface.java | 2 +- .../wamblee/system/core/ContainerTest.java | 878 ++++++++++-------- .../org/wamblee/system/core/Environment.java | 2 +- 4 files changed, 511 insertions(+), 431 deletions(-) diff --git a/system/general/src/main/java/org/wamblee/system/core/Container.java b/system/general/src/main/java/org/wamblee/system/core/Container.java index 1eaebf43..8075abab 100644 --- a/system/general/src/main/java/org/wamblee/system/core/Container.java +++ b/system/general/src/main/java/org/wamblee/system/core/Container.java @@ -25,6 +25,7 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.wamblee.general.Pair; /** * Container consisting of multiple components. @@ -37,29 +38,23 @@ public class Container extends AbstractComponent { private List _components; private Set _componentNames; + private CompositeInterfaceRestriction _restriction; private boolean _sealed; - public static RequiredInterface[] filterRequiredServices( - ProvidedInterface aProvided, - Collection aDescriptors) { - List required = new ArrayList(); - for (RequiredInterface descriptor : aDescriptors) { - if (descriptor.implementedBy(aProvided)) { - required.add(descriptor); - } - } - return required.toArray(new RequiredInterface[0]); - } public static ProvidedInterface[] filterProvidedServices( - RequiredInterface aRequired, Collection aProvided) { - List provided = new ArrayList(); - for (ProvidedInterface descriptor : aProvided) { - if (aRequired.implementedBy(descriptor)) { - provided.add(descriptor); + Component aClient, RequiredInterface aRequired, Collection> aProvided, + InterfaceRestriction aRestriction) { + List result = new ArrayList(); + for (Pair descriptor : aProvided) { + ProvidedInterface provided = descriptor.getFirst(); + Component server = descriptor.getSecond(); + if (aRequired.implementedBy(provided) && + !aRestriction.isViolated(aClient, aRequired, server, provided)) { + result.add(provided); } } - return provided.toArray(new ProvidedInterface[0]); + return result.toArray(new ProvidedInterface[0]); } /** @@ -80,6 +75,7 @@ public class Container extends AbstractComponent { _components = new ArrayList(); _componentNames = new HashSet(); + _restriction = new CompositeInterfaceRestriction(); _sealed = false; for (Component component : aComponents) { addComponent(component); @@ -108,6 +104,18 @@ public class Container extends AbstractComponent { aComponent.addContext(getQualifiedName()); return this; } + + /** + * Adds an interface restriction for explicitly configuring the + * relations between components. + * @param aRestriction Restriction to add. + * @return Reference to this to allow call chaining. + */ + public Container addRestriction(InterfaceRestriction aRestriction) { + checkSealed(); + _restriction.add(aRestriction); + return this; + } @Override public Container addProvidedInterface(ProvidedInterface aProvided) { @@ -235,8 +243,8 @@ public class Container extends AbstractComponent { Scope scope = new DefaultScope(getProvidedInterfaces(), aExternalScope); - List allProvided = new ArrayList(); - + List> allProvided = new ArrayList>(); + addProvidersOfRequiredInterfaces(allProvided); List started = new ArrayList(); @@ -255,7 +263,9 @@ public class Container extends AbstractComponent { // add all provided services ProvidedInterface[] provided = component .getProvidedInterfaces(); - allProvided.addAll(Arrays.asList(provided)); + for (ProvidedInterface prov: provided) { + allProvided.add(new Pair(prov, component)); + } } catch (SystemAssemblyException e) { throw e; } catch (RuntimeException e) { @@ -269,14 +279,14 @@ public class Container extends AbstractComponent { } private void addProvidersOfRequiredInterfaces( - List allProvided) { + List> allProvided) { // all interfaces from the required list of this container are // provided to the components inside it. RequiredInterface[] required = getRequiredInterfaces(); for (RequiredInterface intf : required) { ProvidedInterface provider = intf.getProvider(); if (provider != null) { - allProvided.add(provider); + allProvided.add(new Pair(provider, null)); } else { if (!intf.isOptional()) { throw new SystemAssemblyException(getQualifiedName() @@ -314,15 +324,15 @@ public class Container extends AbstractComponent { * interfaces. */ private void initializeProvidersForRequiredInterfaces( - List aAllProvided, Component aComponent, + List> aAllProvided, Component aComponent, boolean aValidateOnly) { // Check if all required services are already provided by // earlier // systems. for (RequiredInterface descriptor : aComponent.getRequiredInterfaces()) { - ProvidedInterface[] filtered = filterProvidedServices(descriptor, - aAllProvided); + ProvidedInterface[] filtered = filterProvidedServices(aComponent, descriptor, + aAllProvided, _restriction); if (filtered.length == 1) { if (!aValidateOnly) { descriptor.setProvider(filtered[0]); diff --git a/system/general/src/main/java/org/wamblee/system/core/DefaultProvidedInterface.java b/system/general/src/main/java/org/wamblee/system/core/DefaultProvidedInterface.java index 90c230dc..3eb33ddc 100644 --- a/system/general/src/main/java/org/wamblee/system/core/DefaultProvidedInterface.java +++ b/system/general/src/main/java/org/wamblee/system/core/DefaultProvidedInterface.java @@ -36,7 +36,7 @@ public class DefaultProvidedInterface implements ProvidedInterface { this(aName, new Class[] { aInterface }); } - public DefaultProvidedInterface(String aName, Class[] aInterfaces) { + public DefaultProvidedInterface(String aName, Class[] aInterfaces) { _name = aName; _interfaces = Arrays.copyOf(aInterfaces, aInterfaces.length); _uniqueId = null; diff --git a/system/general/src/test/java/org/wamblee/system/core/ContainerTest.java b/system/general/src/test/java/org/wamblee/system/core/ContainerTest.java index 90723ed1..4c451337 100644 --- a/system/general/src/test/java/org/wamblee/system/core/ContainerTest.java +++ b/system/general/src/test/java/org/wamblee/system/core/ContainerTest.java @@ -17,421 +17,491 @@ package org.wamblee.system.core; import java.io.IOException; import java.io.Serializable; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import junit.framework.TestCase; import org.easymock.classextension.ConstructorArgs; import org.easymock.classextension.EasyMock; import org.easymock.classextension.IMocksControl; +import org.wamblee.general.Pair; import org.wamblee.test.AssertionUtils; import org.wamblee.test.EasyMockMatchers; import org.wamblee.test.EventTracker; public class ContainerTest extends TestCase { - private EventTracker _tracker; - - @Override - protected void setUp() throws Exception { - super.setUp(); - _tracker = new EventTracker(); - } - - private static class MyMultiple implements Serializable, Runnable { - @Override - public void run() { - // Empty - } - } - - public void testFilterProvided() { - RequiredInterface req1 = new DefaultRequiredInterface("name", - Runnable.class); - RequiredInterface req2 = new DefaultRequiredInterface("name", - Serializable.class); - ProvidedInterface prov1 = new DefaultProvidedInterface("name", - Runnable.class); - ProvidedInterface prov2 = new DefaultProvidedInterface("name", - Serializable.class); - ProvidedInterface prov3 = new DefaultProvidedInterface("name", - MyMultiple.class); - - AssertionUtils.assertEquals(new RequiredInterface[] { req1 }, Container - .filterRequiredServices(prov1, Arrays - .asList(new RequiredInterface[] { req1 }))); - AssertionUtils.assertEquals(new RequiredInterface[] { req1 }, Container - .filterRequiredServices(prov1, Arrays - .asList(new RequiredInterface[] { req1, req2 }))); - AssertionUtils.assertEquals(new RequiredInterface[] { req1, req2 }, - Container.filterRequiredServices(prov3, Arrays - .asList(new RequiredInterface[] { req1, req2 }))); - - AssertionUtils.assertEquals(new ProvidedInterface[] { prov1 }, - Container.filterProvidedServices(req1, Arrays - .asList(new ProvidedInterface[] { prov1 }))); - AssertionUtils.assertEquals(new ProvidedInterface[] { prov1 }, - Container.filterProvidedServices(req1, Arrays - .asList(new ProvidedInterface[] { prov1, prov2 }))); - AssertionUtils.assertEquals(new ProvidedInterface[] { prov1, prov3 }, - Container.filterProvidedServices(req1, Arrays - .asList(new ProvidedInterface[] { prov1, prov3 }))); - } - - 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().length); - - 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().length); - - 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(); - RequiredInterface[] required = system.getRequiredInterfaces(); - assertEquals(0, required.length); - ProvidedInterface[] provided = system.getProvidedInterfaces(); - assertEquals(0, provided.length); - - 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()[0] - .setProvider(new DefaultProvidedInterface("hallo", Float.class)); - system.start(); - RequiredInterface[] required = system.getRequiredInterfaces(); - assertEquals(1, required.length); - ProvidedInterface[] provided = system.getProvidedInterfaces(); - assertEquals(0, provided.length); - } - - public void testCompositeWithExternalDependencesNotProvided() { - try { - Component environment = new Environment(); - Component application = new Application(); - Container system = new Container("all", - new Component[] { application }, new ProvidedInterface[0], - application.getRequiredInterfaces()); - 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()); - environment.start(new DefaultScope(new ProvidedInterface[0])); - system.getRequiredInterfaces()[0].setProvider(environment - .getProvidedInterfaces()[0]); - system.getRequiredInterfaces()[1].setProvider(environment - .getProvidedInterfaces()[1]); - - system.start(); - RequiredInterface[] required = system.getRequiredInterfaces(); - assertEquals(2, required.length); - ProvidedInterface[] provided = system.getProvidedInterfaces(); - assertEquals(0, provided.length); - - } - - 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()[0].setProvider( - env.getProvidedInterfaces()[0]); - container.getRequiredInterfaces()[1].setProvider( - env.getProvidedInterfaces()[1]); - Scope external = new DefaultScope(env.getProvidedInterfaces()); - env.start(external); - - container.start(external); - assertSame(env.getProvidedInterfaces()[0], container.getRequiredInterfaces()[0].getProvider()); - assertSame(env.getProvidedInterfaces()[1], container.getRequiredInterfaces()[1].getProvider()); - assertSame(env.getProvidedInterfaces()[0], application.getRequiredInterfaces()[0].getProvider()); - assertSame(env.getProvidedInterfaces()[1], application.getRequiredInterfaces()[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()[0].setProvider( - env.getProvidedInterfaces()[0]); - Scope external = new DefaultScope(new ProvidedInterface[0]); - external.publishInterface(env.getProvidedInterfaces()[0], env.getString()); - container.start(external); - assertSame(env.getProvidedInterfaces()[0], container.getRequiredInterfaces()[0].getProvider()); - assertNull(container.getRequiredInterfaces()[1].getProvider()); - assertSame(env.getProvidedInterfaces()[0], application.getRequiredInterfaces()[0].getProvider()); - assertNull(application.getRequiredInterfaces()[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()[0].setProvider( - env.getProvidedInterfaces()[0]); - container.getRequiredInterfaces()[1].setProvider( - env.getProvidedInterfaces()[1]); - container.start(); - assertSame(env.getProvidedInterfaces()[0], container.getRequiredInterfaces()[0].getProvider()); - assertSame(env.getProvidedInterfaces()[1], container.getRequiredInterfaces()[1].getProvider()); - assertSame(env.getProvidedInterfaces()[0], application.getRequiredInterfaces()[0].getProvider()); - assertSame(env.getProvidedInterfaces()[1], application.getRequiredInterfaces()[1].getProvider()); - } - - 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.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); - } + private EventTracker _tracker; + + @Override + protected void setUp() throws Exception { + super.setUp(); + _tracker = new EventTracker(); + } + + private static class MyMultiple implements Serializable, Runnable { + @Override + public void run() { + // Empty + } + } + + private List> createProvidedInput( + ProvidedInterface[] aProvided, Component aProvider) { + List> result = new ArrayList>(); + for (ProvidedInterface provided : aProvided) { + result.add(new Pair(provided, + aProvider)); + } + return result; + } + + public void testFilterProvided() { + RequiredInterface req1 = new DefaultRequiredInterface("name", + Runnable.class); + RequiredInterface req2 = new DefaultRequiredInterface("name", + Serializable.class); + ProvidedInterface prov1 = new DefaultProvidedInterface("name", + Runnable.class); + ProvidedInterface prov2 = new DefaultProvidedInterface("name", + Serializable.class); + ProvidedInterface prov3 = new DefaultProvidedInterface("name", + MyMultiple.class); + + Component client = new Application("client"); + Component dummy = new Application("dummy"); + + InterfaceRestriction noRestriction = new InterfaceRestriction() { + @Override + public boolean isViolated(Component aClient, + RequiredInterface aRequired, Component aServer, + ProvidedInterface aProvided) { + return false; + } + }; + + AssertionUtils.assertEquals(new ProvidedInterface[] { prov1 }, + Container.filterProvidedServices(client, req1, + createProvidedInput(new ProvidedInterface[] { prov1 }, dummy), noRestriction)); + AssertionUtils.assertEquals(new ProvidedInterface[] { prov1 }, + Container.filterProvidedServices(client, req1, + createProvidedInput(new ProvidedInterface[] { prov1, prov2 }, dummy), noRestriction)); + AssertionUtils.assertEquals(new ProvidedInterface[] { prov1, prov3 }, + Container.filterProvidedServices(client, req1, + createProvidedInput(new ProvidedInterface[] { prov1, prov3 }, dummy), noRestriction)); + + InterfaceRestriction everything = new InterfaceRestriction() { + @Override + public boolean isViolated(Component aClient, + RequiredInterface aRequired, Component aServer, + ProvidedInterface aProvided) { + return true; + } + }; + AssertionUtils.assertEquals(new ProvidedInterface[0], + Container.filterProvidedServices(client, req1, + createProvidedInput(new ProvidedInterface[] { prov1, prov3 }, dummy), everything)); + + } + + 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().length); + + 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().length); + + 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(); + RequiredInterface[] required = system.getRequiredInterfaces(); + assertEquals(0, required.length); + ProvidedInterface[] provided = system.getProvidedInterfaces(); + assertEquals(0, provided.length); + + 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()[0] + .setProvider(new DefaultProvidedInterface("hallo", Float.class)); + system.start(); + RequiredInterface[] required = system.getRequiredInterfaces(); + assertEquals(1, required.length); + ProvidedInterface[] provided = system.getProvidedInterfaces(); + assertEquals(0, provided.length); + } + + public void testCompositeWithExternalDependencesNotProvided() { + try { + Component environment = new Environment(); + Component application = new Application(); + Container system = new Container("all", + new Component[] { application }, new ProvidedInterface[0], + application.getRequiredInterfaces()); + 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()); + environment.start(new DefaultScope(new ProvidedInterface[0])); + system.getRequiredInterfaces()[0].setProvider(environment + .getProvidedInterfaces()[0]); + system.getRequiredInterfaces()[1].setProvider(environment + .getProvidedInterfaces()[1]); + + system.start(); + RequiredInterface[] required = system.getRequiredInterfaces(); + assertEquals(2, required.length); + ProvidedInterface[] provided = system.getProvidedInterfaces(); + assertEquals(0, provided.length); + + } + + 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()[0].setProvider(env + .getProvidedInterfaces()[0]); + container.getRequiredInterfaces()[1].setProvider(env + .getProvidedInterfaces()[1]); + Scope external = new DefaultScope(env.getProvidedInterfaces()); + env.start(external); + + container.start(external); + assertSame(env.getProvidedInterfaces()[0], container + .getRequiredInterfaces()[0].getProvider()); + assertSame(env.getProvidedInterfaces()[1], container + .getRequiredInterfaces()[1].getProvider()); + assertSame(env.getProvidedInterfaces()[0], application + .getRequiredInterfaces()[0].getProvider()); + assertSame(env.getProvidedInterfaces()[1], application + .getRequiredInterfaces()[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()[0].setProvider(env + .getProvidedInterfaces()[0]); + Scope external = new DefaultScope(new ProvidedInterface[0]); + external.publishInterface(env.getProvidedInterfaces()[0], env + .getString()); + container.start(external); + assertSame(env.getProvidedInterfaces()[0], container + .getRequiredInterfaces()[0].getProvider()); + assertNull(container.getRequiredInterfaces()[1].getProvider()); + assertSame(env.getProvidedInterfaces()[0], application + .getRequiredInterfaces()[0].getProvider()); + assertNull(application.getRequiredInterfaces()[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()[0].setProvider(env + .getProvidedInterfaces()[0]); + container.getRequiredInterfaces()[1].setProvider(env + .getProvidedInterfaces()[1]); + container.start(); + assertSame(env.getProvidedInterfaces()[0], container + .getRequiredInterfaces()[0].getProvider()); + assertSame(env.getProvidedInterfaces()[1], container + .getRequiredInterfaces()[1].getProvider()); + assertSame(env.getProvidedInterfaces()[0], application + .getRequiredInterfaces()[0].getProvider()); + assertSame(env.getProvidedInterfaces()[1], application + .getRequiredInterfaces()[1].getProvider()); + } + + 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.addRestriction(new InterfaceRestriction() { + @Override + public boolean isViolated(Component aClient, + RequiredInterface aRequired, Component aServer, + ProvidedInterface aProvided) { + return false; + } + }); + } + }, 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.addRestriction(new DefaultInterfaceRestriction("app", null, + "env1", null)); + container.start(); + assertEquals(env1.getString(), app.getString()); + assertFalse(env2.getString().equals(app.getString())); + } } diff --git a/system/general/src/test/java/org/wamblee/system/core/Environment.java b/system/general/src/test/java/org/wamblee/system/core/Environment.java index f176d4aa..c08f456d 100644 --- a/system/general/src/test/java/org/wamblee/system/core/Environment.java +++ b/system/general/src/test/java/org/wamblee/system/core/Environment.java @@ -59,7 +59,7 @@ public class Environment extends AbstractComponent { } public String getString() { - return "Hello"; + return getName() + ".hello"; } @Override -- 2.31.1