/* * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.wamblee.system.container; import junit.framework.TestCase; import org.junit.internal.requests.IgnoredClassRunner; import org.wamblee.general.Pair; import org.wamblee.system.core.Component; import org.wamblee.system.core.DefaultProvidedInterface; import org.wamblee.system.core.DefaultRequiredInterface; import org.wamblee.system.core.DefaultScope; import org.wamblee.system.core.Environment; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; import org.wamblee.system.core.Scope; import org.wamblee.system.core.StringComponent; import org.wamblee.system.core.SystemAssemblyException; import org.wamblee.test.AssertionUtils; import org.wamblee.test.EventTracker; import java.io.Serializable; import java.util.ArrayList; import java.util.List; /** * * @author $author$ * @version $Revision$ */ public class ContainerTest extends TestCase { private EventTracker tracker; @Override protected void setUp() throws Exception { super.setUp(); tracker = new EventTracker(); } 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 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 required = system.getRequiredInterfaces(); assertEquals(0, required.size()); List 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 required = system.getRequiredInterfaces(); assertEquals(1, required.size()); List 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); ignoredVariable(system); ignoredVariable(system2); } catch (SystemAssemblyException e) { return; } fail(); } private static void ignoredVariable(Object aObject) { // for findbugs. } 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 required = system.getRequiredInterfaces(); assertEquals(2, required.size()); List 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 { Environment environment = new Environment(tracker); Application application = new Application() { @Override public Object doStart(Scope aScope) { throw new RuntimeException(); } }; 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 { Environment environment = new Environment(tracker); // Application 1 will throw an exception while stopping. Application application1 = new Application("app1") { @Override public void doStop(Object aRuntime) { throw new RuntimeException(); } }; // application 2 will throw an exception while starting Application application2 = new Application("app2") { public Object doStart(Scope aScope) { throw new RuntimeException(); } }; 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); 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); 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); } private static class MyMultiple implements Serializable, Runnable { @Override public void run() { // Empty } } }