now allowing components and interfaces to be added after construction.
[utils] / system / general / src / test / java / org / wamblee / system / core / ContainerTest.java
index 9bb53a6a6c1a615c7bd4c0218e90a4bc78921679..7eb66757772fb31d1746e6348855c242d1eaf94e 100644 (file)
  * 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.core;
 
+import java.io.IOException;
 import java.io.Serializable;
-import java.util.ArrayList;
 import java.util.Arrays;
 
-import org.wamblee.system.core.Component;
-import org.wamblee.system.core.Container;
-import org.wamblee.system.core.DefaultProvidedInterface;
-import org.wamblee.system.core.DefaultRequiredInterface;
-import org.wamblee.system.core.ProvidedInterface;
-import org.wamblee.system.core.RequiredInterface;
-import org.wamblee.system.core.SystemAssemblyException;
-import org.wamblee.system.core.Component.Status;
+import junit.framework.TestCase;
+
+import org.easymock.classextension.ConstructorArgs;
+import org.easymock.classextension.EasyMock;
+import org.easymock.classextension.IMocksControl;
 import org.wamblee.test.AssertionUtils;
+import org.wamblee.test.EasyMockMatchers;
 import org.wamblee.test.EventTracker;
 
-import junit.framework.TestCase;
-
 public class ContainerTest extends TestCase {
 
        private EventTracker<String> _tracker;
@@ -61,11 +57,11 @@ public class ContainerTest extends TestCase {
                ProvidedInterface prov3 = new DefaultProvidedInterface("name",
                                MyMultiple.class);
 
-               AssertionUtils.assertEquals(new RequiredInterface[] { req1 },
-                               Container.filterRequiredServices(prov1, Arrays
+               AssertionUtils.assertEquals(new RequiredInterface[] { req1 }, Container
+                               .filterRequiredServices(prov1, Arrays
                                                .asList(new RequiredInterface[] { req1 })));
-               AssertionUtils.assertEquals(new RequiredInterface[] { req1 },
-                               Container.filterRequiredServices(prov1, Arrays
+               AssertionUtils.assertEquals(new RequiredInterface[] { req1 }, Container
+                               .filterRequiredServices(prov1, Arrays
                                                .asList(new RequiredInterface[] { req1, req2 })));
                AssertionUtils.assertEquals(new RequiredInterface[] { req1, req2 },
                                Container.filterRequiredServices(prov3, Arrays
@@ -83,32 +79,48 @@ public class ContainerTest extends TestCase {
        }
 
        public void testEnvironmentApplication() {
-               Component environment = new Environment(_tracker);
-               Component application = new Application(_tracker);
+               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]);
-                               
-               container.start();
+
+               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]));
-               ProvidedInterface[] envServices = environment.getRunningServices();
-               assertEquals(2, envServices.length);
-               ProvidedInterface[] appServices = environment.getRunningServices();
-               assertEquals(2, appServices.length);
+               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 container = new Container("root", new Component[] {
+                                       application, environment }, new ProvidedInterface[0],
+                                       new RequiredInterface[0]);
                        container.start();
                } catch (SystemAssemblyException e) {
                        // e.printStackTrace();
@@ -121,37 +133,26 @@ public class ContainerTest extends TestCase {
                Component environment = new Environment(_tracker);
                Component application = new Application(_tracker);
                assertEquals(0, _tracker.getEventCount());
-               assertEquals(Status.NOT_STARTED, environment.getStatus());
-               assertEquals(Status.NOT_STARTED, application.getStatus());
-               
+
                Container system = new Container("all", new Component[] { environment,
                                application }, new ProvidedInterface[0],
                                new RequiredInterface[0]);
-               assertEquals(Status.NOT_STARTED, system.getStatus());
-               system.start();
-               RequiredInterface[] required = system.getRequiredServices();
+               Scope runtime = system.start();
+               RequiredInterface[] required = system.getRequiredInterfaces();
                assertEquals(0, required.length);
-               ProvidedInterface[] provided = system.getProvidedServices();
+               ProvidedInterface[] provided = system.getProvidedInterfaces();
                assertEquals(0, provided.length);
-               assertEquals(Status.RUNNING, environment.getStatus());
-               assertEquals(Status.RUNNING, application.getStatus());
-               assertEquals(Status.RUNNING, system.getStatus());
-               
-               AssertionUtils.assertEquals(
-                               new String[] { "start.environment", "start.application" }, 
-                               _tracker.getEvents(Thread.currentThread()).toArray(new String[0]));
-        _tracker.clear();
-               
-               system.stop();
-               assertEquals(Status.STOPPED, environment.getStatus());
-               assertEquals(Status.STOPPED, application.getStatus());
-               assertEquals(Status.STOPPED, system.getStatus());
-               
-               AssertionUtils.assertEquals(
-                               new String[] { "stop.application", "stop.environment" }, 
-                               _tracker.getEvents(Thread.currentThread()).toArray(new String[0]));
-      
-               
+
+               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() {
@@ -161,7 +162,7 @@ public class ContainerTest extends TestCase {
                        Container system = new Container("all", new Component[] {
                                        environment, application },
                                        new ProvidedInterface[] { new DefaultProvidedInterface(
-                                                       "string", String.class) },
+                                                       "float", Float.class) },
                                        new DefaultRequiredInterface[0]);
                } catch (SystemAssemblyException e) {
                        return;
@@ -190,13 +191,13 @@ public class ContainerTest extends TestCase {
                Container system = new Container("all", new Component[] { environment,
                                application }, new ProvidedInterface[0],
                                new RequiredInterface[] { new DefaultRequiredInterface(
-                                               "string", String.class) });
-               system.getRequiredServices()[0]
-                               .setProvider(new DefaultProvidedInterface("hallo", String.class));
+                                               "float", Float.class) });
+               system.getRequiredInterfaces()[0]
+                               .setProvider(new DefaultProvidedInterface("hallo", Float.class));
                system.start();
-               RequiredInterface[] required = system.getRequiredServices();
+               RequiredInterface[] required = system.getRequiredInterfaces();
                assertEquals(1, required.length);
-               ProvidedInterface[] provided = system.getProvidedServices();
+               ProvidedInterface[] provided = system.getProvidedInterfaces();
                assertEquals(0, provided.length);
        }
 
@@ -206,7 +207,7 @@ public class ContainerTest extends TestCase {
                        Component application = new Application();
                        Container system = new Container("all",
                                        new Component[] { application }, new ProvidedInterface[0],
-                                       application.getRequiredServices());
+                                       application.getRequiredInterfaces());
                        system.start();
                } catch (SystemAssemblyException e) {
                        return;
@@ -221,17 +222,17 @@ public class ContainerTest extends TestCase {
                Component application = new Application();
                Container system = new Container("all",
                                new Component[] { application }, new ProvidedInterface[0],
-                               application.getRequiredServices());
-               environment.start();
-               system.getRequiredServices()[0].setProvider(environment
-                               .getProvidedServices()[0]);
-               system.getRequiredServices()[1].setProvider(environment
-                               .getProvidedServices()[1]);
+                               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.getRequiredServices();
+               RequiredInterface[] required = system.getRequiredInterfaces();
                assertEquals(2, required.length);
-               ProvidedInterface[] provided = system.getProvidedServices();
+               ProvidedInterface[] provided = system.getProvidedInterfaces();
                assertEquals(0, provided.length);
 
        }
@@ -265,4 +266,148 @@ public class ContainerTest extends TestCase {
                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()),
+                               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); 
+       }
 }