/* * Copyright 2007 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 java.io.Serializable; import java.util.ArrayList; 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.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.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 } } 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().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())); } 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()[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])); } }