2 * Copyright 2007 the original author or authors.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.wamblee.system.container;
18 import junit.framework.TestCase;
20 import org.wamblee.general.Pair;
22 import org.wamblee.system.core.Component;
23 import org.wamblee.system.core.DefaultProvidedInterface;
24 import org.wamblee.system.core.DefaultRequiredInterface;
25 import org.wamblee.system.core.DefaultScope;
26 import org.wamblee.system.core.Environment;
27 import org.wamblee.system.core.ProvidedInterface;
28 import org.wamblee.system.core.RequiredInterface;
29 import org.wamblee.system.core.Scope;
30 import org.wamblee.system.core.StringComponent;
31 import org.wamblee.system.core.SystemAssemblyException;
33 import org.wamblee.test.AssertionUtils;
34 import org.wamblee.test.EventTracker;
36 import java.io.Serializable;
38 import java.util.ArrayList;
39 import java.util.List;
48 public class ContainerTest extends TestCase {
52 private EventTracker<String> tracker;
57 * @throws Exception DOCUMENT ME!
60 protected void setUp() throws Exception {
62 tracker = new EventTracker<String>();
68 * @param aProvided DOCUMENT ME!
69 * @param aProvider DOCUMENT ME!
71 * @return DOCUMENT ME!
73 private List<Pair<ProvidedInterface, Component>> createProvidedInput(
74 ProvidedInterface[] aProvided, Component aProvider) {
75 List<Pair<ProvidedInterface, Component>> result = new ArrayList<Pair<ProvidedInterface, Component>>();
77 for (ProvidedInterface provided : aProvided) {
78 result.add(new Pair<ProvidedInterface, Component>(provided,
88 public void testEnvironmentApplication() {
89 Environment environment = new Environment(tracker);
90 Application application = new Application(tracker);
91 Container container = new Container("root",
92 new Component[] { environment, application },
93 new ProvidedInterface[0], new RequiredInterface[0]);
94 Scope scope = container.start();
95 assertTrue(container.isSealed());
96 AssertionUtils.assertEquals(new String[] {
97 "start.environment", "start.application"
98 }, tracker.getEvents(Thread.currentThread()).toArray(new String[0]));
99 assertEquals(0, scope.getProvidedInterfaces().size());
101 assertEquals(environment.getString(), application.getString());
102 assertEquals(environment.getInteger(), application.getInteger());
108 public void testEnvironmentApplicationSimpleConstructor() {
109 Environment environment = new Environment(tracker);
110 Application application = new Application(tracker);
111 Container container = new Container("root").addComponent(environment)
112 .addComponent(application);
114 Scope scope = container.start();
115 AssertionUtils.assertEquals(new String[] {
116 "start.environment", "start.application"
117 }, tracker.getEvents(Thread.currentThread()).toArray(new String[0]));
118 assertEquals(0, scope.getProvidedInterfaces().size());
120 assertEquals(environment.getString(), application.getString());
121 assertEquals(environment.getInteger(), application.getInteger());
127 public void testApplicationEnvironment() {
129 Component<?> environment = new Environment();
130 Component<?> application = new Application();
131 Container container = new Container("root",
132 new Component[] { application, environment },
133 new ProvidedInterface[0], new RequiredInterface[0]);
135 } catch (SystemAssemblyException e) {
136 // e.printStackTrace();
146 public void testComposite() {
147 Component<?> environment = new Environment(tracker);
148 Component<?> application = new Application(tracker);
149 assertEquals(0, tracker.getEventCount());
151 Container system = new Container("all",
152 new Component[] { environment, application },
153 new ProvidedInterface[0], new RequiredInterface[0]);
154 Scope runtime = system.start();
155 List<RequiredInterface> required = system.getRequiredInterfaces();
156 assertEquals(0, required.size());
158 List<ProvidedInterface> provided = system.getProvidedInterfaces();
159 assertEquals(0, provided.size());
161 AssertionUtils.assertEquals(new String[] {
162 "start.environment", "start.application"
163 }, tracker.getEvents(Thread.currentThread()).toArray(new String[0]));
166 system.stop(runtime);
167 AssertionUtils.assertEquals(new String[] {
168 "stop.application", "stop.environment"
169 }, tracker.getEvents(Thread.currentThread()).toArray(new String[0]));
175 public void testCompositeWithWrongProvidedInfo() {
177 Component<?> environment = new Environment();
178 Component<?> application = new Application();
179 Container system = new Container("all",
180 new Component[] { environment, application },
181 new ProvidedInterface[] {
182 new DefaultProvidedInterface("float", Float.class)
183 }, new DefaultRequiredInterface[0]);
185 } catch (SystemAssemblyException e) {
195 public void testCompositeRequiredInterfaceNotProvided() {
197 Component<?> environment = new Environment();
198 Component<?> application = new Application();
199 Container system = new Container("all",
200 new Component[] { environment, application },
201 new ProvidedInterface[0],
202 new RequiredInterface[] {
203 new DefaultRequiredInterface("string", String.class)
206 } catch (SystemAssemblyException e) {
216 public void testCompositeWithSuperfluousRequiredInfo() {
217 Component<?> environment = new Environment();
218 Component<?> application = new Application();
219 Container system = new Container("all",
220 new Component[] { environment, application },
221 new ProvidedInterface[0],
222 new RequiredInterface[] {
223 new DefaultRequiredInterface("float", Float.class)
225 system.getRequiredInterfaces().get(0)
226 .setProvider(new DefaultProvidedInterface("hallo", Float.class));
229 List<RequiredInterface> required = system.getRequiredInterfaces();
230 assertEquals(1, required.size());
232 List<ProvidedInterface> provided = system.getProvidedInterfaces();
233 assertEquals(0, provided.size());
239 public void testCompositeWithExternalDependencesNotProvided() {
241 Component<?> application = new Application();
243 Container system = new Container("all",
244 new Component[] { application }, new ProvidedInterface[0],
245 application.getRequiredInterfaces()
246 .toArray(new RequiredInterface[0]));
248 } catch (SystemAssemblyException e) {
258 public void testDuplicateComponent() {
260 Component<?> comp1 = new Application();
261 Component<?> comp2 = new Application();
262 Container system = new Container("top");
263 system.addComponent(comp1).addComponent(comp2);
264 } catch (SystemAssemblyException e) {
274 public void testInconsistentHierarchy() {
276 Component<?> comp = new Application();
277 Container system = new Container("top").addComponent(comp);
278 Container system2 = new Container("top2").addComponent(comp);
279 } catch (SystemAssemblyException e) {
289 public void testCompositeWithExternalDependencesProvided() {
290 Component<?> environment = new Environment();
291 Component<?> application = new Application();
292 Container system = new Container("all",
293 new Component[] { application }, new ProvidedInterface[0],
294 application.getRequiredInterfaces()
295 .toArray(new RequiredInterface[0]));
296 environment.start(new DefaultScope(new ProvidedInterface[0]));
297 system.getRequiredInterfaces().get(0)
298 .setProvider(environment.getProvidedInterfaces().get(0));
299 system.getRequiredInterfaces().get(1)
300 .setProvider(environment.getProvidedInterfaces().get(1));
304 List<RequiredInterface> required = system.getRequiredInterfaces();
305 assertEquals(2, required.size());
307 List<ProvidedInterface> provided = system.getProvidedInterfaces();
308 assertEquals(0, provided.size());
314 public void testAmbiguousInterfaces() {
316 Component<?> environment1 = new Environment();
317 Component<?> environment2 = new Environment();
318 Component<?> application = new Application();
319 Container container = new Container("root",
320 new Component[] { environment1, environment2, application },
321 new ProvidedInterface[0], new RequiredInterface[0]);
323 } catch (SystemAssemblyException e) {
333 public void testIncompleteRequirements() {
335 Component<?> application = new Application();
336 Container system = new Container("all",
337 new Component[] { application }, new ProvidedInterface[0],
338 new RequiredInterface[0]);
340 } catch (SystemAssemblyException e) {
350 * @throws Exception DOCUMENT ME!
351 * @throws RuntimeException DOCUMENT ME!
353 public void testEnvironmentApplicationRollbackOnException()
355 Environment environment = new Environment(tracker);
356 Application application = new Application() {
358 public Object doStart(Scope aScope) {
359 throw new RuntimeException();
364 Container container = new Container("root",
365 new Component[] { environment, application },
366 new ProvidedInterface[0], new RequiredInterface[0]);
369 } catch (RuntimeException e) {
370 AssertionUtils.assertEquals(new String[] {
371 "start.environment", "stop.environment"
373 tracker.getEvents(Thread.currentThread()).toArray(new String[0]));
384 * @throws Exception DOCUMENT ME!
385 * @throws RuntimeException DOCUMENT ME!
387 public void testEnvironmentApplicationRollbackOnExceptionWithExceptionOnStop()
389 Environment environment = new Environment(tracker);
391 // Application 1 will throw an exception while stopping.
392 Application application1 = new Application("app1") {
394 public void doStop(Object aRuntime) {
395 throw new RuntimeException();
399 // application 2 will throw an exception while starting
400 Application application2 = new Application("app2") {
401 public Object doStart(Scope aScope) {
402 throw new RuntimeException();
407 Container container = new Container("root",
408 new Component[] { environment, application1, application2 },
409 new ProvidedInterface[0], new RequiredInterface[0]);
412 } catch (RuntimeException e) {
413 AssertionUtils.assertEquals(new String[] {
414 "start.environment", "stop.environment"
416 tracker.getEvents(Thread.currentThread()).toArray(new String[0]));
427 public void testOptionalRequiredInterfaceProvidedOptionalInternal() {
428 Application application = new Application(true);
429 Container container = new Container("top",
430 new Component[] { application }, new ProvidedInterface[0],
431 Application.required(true));
432 Environment env = new Environment();
433 container.getRequiredInterfaces().get(0)
434 .setProvider(env.getProvidedInterfaces().get(0));
435 container.getRequiredInterfaces().get(1)
436 .setProvider(env.getProvidedInterfaces().get(1));
438 Scope external = new DefaultScope(env.getProvidedInterfaces());
441 container.start(external);
442 assertSame(env.getProvidedInterfaces().get(0),
443 container.getRequiredInterfaces().get(0).getProvider());
444 assertSame(env.getProvidedInterfaces().get(1),
445 container.getRequiredInterfaces().get(1).getProvider());
446 assertSame(env.getProvidedInterfaces().get(0),
447 application.getRequiredInterfaces().get(0).getProvider());
448 assertSame(env.getProvidedInterfaces().get(1),
449 application.getRequiredInterfaces().get(1).getProvider());
455 public void testOptionalRequiredInterfaceNotProvidedOptionalInternal() {
456 Application application = new Application(true);
457 Container container = new Container("top",
458 new Component[] { application }, new ProvidedInterface[0],
459 Application.required(true));
460 Environment env = new Environment();
461 container.getRequiredInterfaces().get(0)
462 .setProvider(env.getProvidedInterfaces().get(0));
464 Scope external = new DefaultScope(new ProvidedInterface[0]);
465 external.publishInterface(env.getProvidedInterfaces().get(0),
467 container.start(external);
468 assertSame(env.getProvidedInterfaces().get(0),
469 container.getRequiredInterfaces().get(0).getProvider());
470 assertNull(container.getRequiredInterfaces().get(1).getProvider());
471 assertSame(env.getProvidedInterfaces().get(0),
472 application.getRequiredInterfaces().get(0).getProvider());
473 assertNull(application.getRequiredInterfaces().get(1).getProvider());
479 public void testOptionalRequiredInterfaceProvidedMandatoryInternal() {
480 Application application = new Application();
481 Container container = new Container("top",
482 new Component[] { application }, new ProvidedInterface[0],
483 Application.required(true));
484 Environment env = new Environment();
485 container.getRequiredInterfaces().get(0)
486 .setProvider(env.getProvidedInterfaces().get(0));
487 container.getRequiredInterfaces().get(1)
488 .setProvider(env.getProvidedInterfaces().get(1));
492 } catch (SystemAssemblyException e) {
502 public void testSealed() {
503 final Container container = new Container("xx");
504 assertFalse(container.isSealed());
506 assertTrue(container.isSealed());
508 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
510 public void run() throws Exception {
511 container.addComponent(new Application());
513 }, SystemAssemblyException.class);
515 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
517 public void run() throws Exception {
518 container.connectRequiredProvided("x", "y", "a", "b");
520 }, SystemAssemblyException.class);
521 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
523 public void run() throws Exception {
524 container.connectExternalRequired("x", "y", "a");
526 }, SystemAssemblyException.class);
527 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
529 public void run() throws Exception {
530 container.connectExternalProvided("x", "y", "z");
532 }, SystemAssemblyException.class);
533 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
535 public void run() throws Exception {
536 container.addProvidedInterface(new DefaultProvidedInterface(
537 "xx", String.class));
539 }, SystemAssemblyException.class);
541 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
543 public void run() throws Exception {
544 container.addRequiredInterface(new DefaultRequiredInterface(
545 "xx", String.class));
547 }, SystemAssemblyException.class);
553 public void testRestriction() {
554 Environment env1 = new Environment("env1");
555 Environment env2 = new Environment("env2");
556 Application app = new Application("app");
557 Container container = new Container("top").addComponent(env1)
558 .addComponent(env2).addComponent(app);
559 container.connectRequiredProvided("app", null, "env1", null);
561 assertEquals(env1.getString(), app.getString());
562 assertEquals(env1.getInteger(), app.getInteger());
563 assertFalse(env2.getString().equals(app.getString()));
564 assertFalse(env2.getInteger().equals(app.getInteger()));
570 public void testRestrictionWithFromAndToInterfaceName() {
571 Environment env1 = new Environment("env1");
572 Environment env2 = new Environment("env2");
573 Application app = new Application("app");
574 Container container = new Container("top").addComponent(env1)
575 .addComponent(env2).addComponent(app);
576 container.connectRequiredProvided("app",
577 app.getRequiredInterfaces().get(0).getName(), "env1",
578 env1.getProvidedInterfaces().get(0).getName());
579 container.connectRequiredProvided("app",
580 app.getRequiredInterfaces().get(1).getName(), "env2",
581 env2.getProvidedInterfaces().get(1).getName());
583 assertEquals(env1.getString(), app.getString());
584 assertEquals(env2.getInteger(), app.getInteger());
585 assertFalse(env2.getString().equals(app.getString()));
586 assertFalse(env1.getInteger().equals(app.getInteger()));
592 public void testRestrictionWrongComponentNames() {
593 Environment env1 = new Environment("env1");
594 Environment env2 = new Environment("env2");
595 Application app = new Application("app");
596 final Container container = new Container("top").addComponent(env1)
597 .addComponent(env2).addComponent(app);
598 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
600 public void run() throws Exception {
601 container.connectRequiredProvided("app2", null, "env1", null);
603 }, SystemAssemblyException.class);
604 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
606 public void run() throws Exception {
607 container.connectRequiredProvided("app", null, "env3", null);
609 }, SystemAssemblyException.class);
615 public void testRestrictionWrongInterfaceNames() {
616 final Environment env1 = new Environment("env1");
617 Environment env2 = new Environment("env2");
618 final Application app = new Application("app");
619 final Container container = new Container("top").addComponent(env1)
620 .addComponent(env2).addComponent(app);
621 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
623 public void run() throws Exception {
624 container.connectRequiredProvided("app",
625 app.getRequiredInterfaces().get(0).getName() + "xxx",
628 }, SystemAssemblyException.class);
629 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
631 public void run() throws Exception {
632 container.connectRequiredProvided("app", null, "env1",
633 env1.getProvidedInterfaces().get(0).getName() + "yyy");
635 }, SystemAssemblyException.class);
641 public void testProvidedInDifferentScopes() {
642 // Scoping problem occurred. Externally and internally provided
643 // components clashed
644 // because unique id generation in the scope was wrong.
645 StringComponent str = new StringComponent("string");
646 Application app = new Application("app");
647 Container container = new Container("top").addComponent(str)
649 container.addRequiredInterface(new DefaultRequiredInterface("integer",
652 ProvidedInterface provided = new DefaultProvidedInterface("hallo",
654 container.getRequiredInterfaces().get(0).setProvider(provided);
656 Scope external = new DefaultScope(new ProvidedInterface[0]);
657 external.publishInterface(provided, 100);
659 Scope scope = container.start(external);
665 public void testProvidedInterfaces() {
666 Environment env = new Environment(tracker);
667 Container envcontainer = new Container("0").addComponent(env)
668 .addProvidedInterface(new DefaultProvidedInterface("string",
670 .addProvidedInterface(new DefaultProvidedInterface("integer",
672 Scope scope = envcontainer.start();
674 AssertionUtils.assertEquals(new String[] { "start.environment" },
675 tracker.getEvents(Thread.currentThread()).toArray(new String[0]));
677 envcontainer.stop(scope);
683 public void testCoupleTwoContainers() {
684 Environment env = new Environment(tracker);
685 Container envcontainer = new Container("0").addComponent(env)
686 .addProvidedInterface(new DefaultProvidedInterface("string",
688 .addProvidedInterface(new DefaultProvidedInterface("integer",
691 Application app = new Application(tracker);
692 Container appcontainer = new Container("1").addComponent(app)
693 .addRequiredInterface(new DefaultRequiredInterface("string",
695 .addRequiredInterface(new DefaultRequiredInterface("integer",
698 Container top = new Container("top");
699 top.addComponent(envcontainer).addComponent(appcontainer);
702 AssertionUtils.assertEquals(new String[] {
703 "start.environment", "start.application"
704 }, tracker.getEvents(Thread.currentThread()).toArray(new String[0]));
710 public void testNonUniqueRequiredInterface() {
711 final Container container = new Container("top");
712 container.addRequiredInterface(new DefaultRequiredInterface("i",
714 container.addRequiredInterface(new DefaultRequiredInterface("x",
716 container.addRequiredInterface(new DefaultRequiredInterface("y",
719 Application app = new Application("1");
720 container.addComponent(app);
722 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
724 public void run() throws Exception {
727 }, SystemAssemblyException.class);
729 container.connectExternalRequired("1",
730 app.getRequiredInterfaces().get(0).getName(), "y");
732 ProvidedInterface i = new DefaultProvidedInterface("i",
734 ProvidedInterface x = new DefaultProvidedInterface("x",
736 ProvidedInterface y = new DefaultProvidedInterface("y",
739 Scope externalScope = new DefaultScope(new ProvidedInterface[0]);
741 externalScope.publishInterface(i, 100);
742 externalScope.publishInterface(x, "x-value");
743 externalScope.publishInterface(y, "y-value");
745 container.getRequiredInterfaces().get(0).setProvider(i);
746 container.getRequiredInterfaces().get(1).setProvider(x);
747 container.getRequiredInterfaces().get(2).setProvider(y);
749 Scope runtime = container.start(externalScope);
751 assertEquals("y-value", app.getString());
757 public void testNonUniqueRequiredInterfaceWrongNames() {
758 final Container container = new Container("top");
759 container.addRequiredInterface(new DefaultRequiredInterface("i",
761 container.addRequiredInterface(new DefaultRequiredInterface("x",
763 container.addRequiredInterface(new DefaultRequiredInterface("y",
766 final Application app = new Application("1");
767 container.addComponent(app);
769 // wrong component name.
770 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
772 public void run() throws Exception {
773 container.connectExternalRequired("2", "x", "y");
775 }, SystemAssemblyException.class);
777 // Wrong interface name of component.
778 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
780 public void run() throws Exception {
781 container.connectExternalRequired("1",
782 app.getRequiredInterfaces().get(0).getName() + "xxx",
785 }, SystemAssemblyException.class);
787 // Wrong external interface name of container
788 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
790 public void run() throws Exception {
791 container.connectExternalRequired("1",
792 app.getRequiredInterfaces().get(0).getName(), "z");
794 }, SystemAssemblyException.class);
800 public void testNonUniqueProvidedInterface() {
801 final Container container = new Container("top").addProvidedInterface(new DefaultProvidedInterface(
802 "external", String.class));
803 Environment env1 = new Environment("env1");
804 Environment env2 = new Environment("env2");
806 container.addComponent(env1);
807 container.addComponent(env2);
809 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
811 public void run() throws Exception {
814 }, SystemAssemblyException.class);
817 container.connectExternalProvided(container.getProvidedInterfaces()
818 .get(0).getName(), env2.getName(),
819 env2.getProvidedInterfaces().get(0).getName());
821 Scope scope = container.start();
823 // check the value of the provided interface of the container
824 String value = scope.getInterfaceImplementation(container.getProvidedInterfaces()
825 .get(0), String.class);
826 assertNotNull(value);
827 assertEquals(value, env2.getString());
828 assertFalse(value.equals(env1.getString()));
834 public void testNonUniqueProvidedInterfaceWrongNames() {
835 final Container container = new Container("top").addProvidedInterface(new DefaultProvidedInterface(
836 "external", String.class));
837 final Environment env1 = new Environment("env1");
838 final Environment env2 = new Environment("env2");
840 container.addComponent(env1);
841 container.addComponent(env2);
843 // Wrong external provided interface name
844 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
846 public void run() throws Exception {
847 container.connectExternalProvided(container.getProvidedInterfaces()
848 .get(0).getName() + "xx", "env1",
849 env1.getProvidedInterfaces().get(0).getName());
851 }, SystemAssemblyException.class);
853 // Wrong provided interface name.
854 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
856 public void run() throws Exception {
857 container.connectExternalProvided(container.getProvidedInterfaces()
858 .get(0).getName(), "env1",
859 env1.getProvidedInterfaces().get(0).getName() + "xx");
861 }, SystemAssemblyException.class);
863 // Wrong provided component
864 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
866 public void run() throws Exception {
867 container.connectExternalProvided(container.getProvidedInterfaces()
868 .get(0).getName(), "env3",
869 env1.getProvidedInterfaces().get(0).getName());
871 }, SystemAssemblyException.class);
874 private static class MyMultiple implements Serializable, Runnable {