2 * Copyright 2005-2010 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;
46 public class ContainerTest extends TestCase {
47 private EventTracker<String> tracker;
50 protected void setUp() throws Exception {
52 tracker = new EventTracker<String>();
55 private List<Pair<ProvidedInterface, Component>> createProvidedInput(
56 ProvidedInterface[] aProvided, Component aProvider) {
57 List<Pair<ProvidedInterface, Component>> result = new ArrayList<Pair<ProvidedInterface, Component>>();
59 for (ProvidedInterface provided : aProvided) {
60 result.add(new Pair<ProvidedInterface, Component>(provided,
67 public void testEnvironmentApplication() {
68 Environment environment = new Environment(tracker);
69 Application application = new Application(tracker);
70 Container container = new Container("root", new Component[] {
71 environment, application }, new ProvidedInterface[0],
72 new RequiredInterface[0]);
73 Scope scope = container.start();
74 assertTrue(container.isSealed());
75 AssertionUtils.assertEquals(new String[] { "start.environment",
76 "start.application" }, tracker.getEvents(Thread.currentThread())
77 .toArray(new String[0]));
78 assertEquals(0, scope.getProvidedInterfaces().size());
80 assertEquals(environment.getString(), application.getString());
81 assertEquals(environment.getInteger(), application.getInteger());
84 public void testEnvironmentApplicationSimpleConstructor() {
85 Environment environment = new Environment(tracker);
86 Application application = new Application(tracker);
87 Container container = new Container("root").addComponent(environment)
88 .addComponent(application);
90 Scope scope = container.start();
91 AssertionUtils.assertEquals(new String[] { "start.environment",
92 "start.application" }, tracker.getEvents(Thread.currentThread())
93 .toArray(new String[0]));
94 assertEquals(0, scope.getProvidedInterfaces().size());
96 assertEquals(environment.getString(), application.getString());
97 assertEquals(environment.getInteger(), application.getInteger());
100 public void testApplicationEnvironment() {
102 Component<?> environment = new Environment();
103 Component<?> application = new Application();
104 Container container = new Container("root", new Component[] {
105 application, environment }, new ProvidedInterface[0],
106 new RequiredInterface[0]);
108 } catch (SystemAssemblyException e) {
109 // e.printStackTrace();
116 public void testComposite() {
117 Component<?> environment = new Environment(tracker);
118 Component<?> application = new Application(tracker);
119 assertEquals(0, tracker.getEventCount());
121 Container system = new Container("all", new Component[] { environment,
122 application }, new ProvidedInterface[0], new RequiredInterface[0]);
123 Scope runtime = system.start();
124 List<RequiredInterface> required = system.getRequiredInterfaces();
125 assertEquals(0, required.size());
127 List<ProvidedInterface> provided = system.getProvidedInterfaces();
128 assertEquals(0, provided.size());
130 AssertionUtils.assertEquals(new String[] { "start.environment",
131 "start.application" }, tracker.getEvents(Thread.currentThread())
132 .toArray(new String[0]));
135 system.stop(runtime);
136 AssertionUtils.assertEquals(new String[] { "stop.application",
137 "stop.environment" }, tracker.getEvents(Thread.currentThread())
138 .toArray(new String[0]));
141 public void testCompositeWithWrongProvidedInfo() {
143 Component<?> environment = new Environment();
144 Component<?> application = new Application();
145 Container system = new Container("all", new Component[] {
146 environment, application },
147 new ProvidedInterface[] { new DefaultProvidedInterface("float",
148 Float.class) }, new DefaultRequiredInterface[0]);
150 } catch (SystemAssemblyException e) {
157 public void testCompositeRequiredInterfaceNotProvided() {
159 Component<?> environment = new Environment();
160 Component<?> application = new Application();
161 Container system = new Container("all", new Component[] {
162 environment, application }, new ProvidedInterface[0],
163 new RequiredInterface[] { new DefaultRequiredInterface(
164 "string", String.class) });
166 } catch (SystemAssemblyException e) {
173 public void testCompositeWithSuperfluousRequiredInfo() {
174 Component<?> environment = new Environment();
175 Component<?> application = new Application();
176 Container system = new Container("all", new Component[] { environment,
177 application }, new ProvidedInterface[0],
178 new RequiredInterface[] { new DefaultRequiredInterface("float",
180 system.getRequiredInterfaces().get(0).setProvider(
181 new DefaultProvidedInterface("hallo", Float.class));
184 List<RequiredInterface> required = system.getRequiredInterfaces();
185 assertEquals(1, required.size());
187 List<ProvidedInterface> provided = system.getProvidedInterfaces();
188 assertEquals(0, provided.size());
191 public void testCompositeWithExternalDependencesNotProvided() {
193 Component<?> application = new Application();
195 Container system = new Container("all",
196 new Component[] { application }, new ProvidedInterface[0],
197 application.getRequiredInterfaces().toArray(
198 new RequiredInterface[0]));
200 } catch (SystemAssemblyException e) {
207 public void testDuplicateComponent() {
209 Component<?> comp1 = new Application();
210 Component<?> comp2 = new Application();
211 Container system = new Container("top");
212 system.addComponent(comp1).addComponent(comp2);
213 } catch (SystemAssemblyException e) {
220 public void testInconsistentHierarchy() {
222 Component<?> comp = new Application();
223 Container system = new Container("top").addComponent(comp);
224 Container system2 = new Container("top2").addComponent(comp);
225 } catch (SystemAssemblyException e) {
232 public void testCompositeWithExternalDependencesProvided() {
233 Component<?> environment = new Environment();
234 Component<?> application = new Application();
235 Container system = new Container("all",
236 new Component[] { application }, new ProvidedInterface[0],
237 application.getRequiredInterfaces().toArray(
238 new RequiredInterface[0]));
239 environment.start(new DefaultScope(new ProvidedInterface[0]));
240 system.getRequiredInterfaces().get(0).setProvider(
241 environment.getProvidedInterfaces().get(0));
242 system.getRequiredInterfaces().get(1).setProvider(
243 environment.getProvidedInterfaces().get(1));
247 List<RequiredInterface> required = system.getRequiredInterfaces();
248 assertEquals(2, required.size());
250 List<ProvidedInterface> provided = system.getProvidedInterfaces();
251 assertEquals(0, provided.size());
254 public void testAmbiguousInterfaces() {
256 Component<?> environment1 = new Environment();
257 Component<?> environment2 = new Environment();
258 Component<?> application = new Application();
259 Container container = new Container("root", new Component[] {
260 environment1, environment2, application },
261 new ProvidedInterface[0], new RequiredInterface[0]);
263 } catch (SystemAssemblyException e) {
270 public void testIncompleteRequirements() {
272 Component<?> application = new Application();
273 Container system = new Container("all",
274 new Component[] { application }, new ProvidedInterface[0],
275 new RequiredInterface[0]);
277 } catch (SystemAssemblyException e) {
284 public void testEnvironmentApplicationRollbackOnException()
286 Environment environment = new Environment(tracker);
287 Application application = new Application() {
289 public Object doStart(Scope aScope) {
290 throw new RuntimeException();
295 Container container = new Container("root", new Component[] {
296 environment, application }, new ProvidedInterface[0],
297 new RequiredInterface[0]);
300 } catch (RuntimeException e) {
301 AssertionUtils.assertEquals(new String[] { "start.environment",
302 "stop.environment" }, tracker.getEvents(Thread.currentThread())
303 .toArray(new String[0]));
311 public void testEnvironmentApplicationRollbackOnExceptionWithExceptionOnStop()
313 Environment environment = new Environment(tracker);
315 // Application 1 will throw an exception while stopping.
316 Application application1 = new Application("app1") {
318 public void doStop(Object aRuntime) {
319 throw new RuntimeException();
323 // application 2 will throw an exception while starting
324 Application application2 = new Application("app2") {
325 public Object doStart(Scope aScope) {
326 throw new RuntimeException();
331 Container container = new Container("root", new Component[] {
332 environment, application1, application2 },
333 new ProvidedInterface[0], new RequiredInterface[0]);
336 } catch (RuntimeException e) {
337 AssertionUtils.assertEquals(new String[] { "start.environment",
338 "stop.environment" }, tracker.getEvents(Thread.currentThread())
339 .toArray(new String[0]));
347 public void testOptionalRequiredInterfaceProvidedOptionalInternal() {
348 Application application = new Application(true);
349 Container container = new Container("top",
350 new Component[] { application }, new ProvidedInterface[0],
351 Application.required(true));
352 Environment env = new Environment();
353 container.getRequiredInterfaces().get(0).setProvider(
354 env.getProvidedInterfaces().get(0));
355 container.getRequiredInterfaces().get(1).setProvider(
356 env.getProvidedInterfaces().get(1));
358 Scope external = new DefaultScope(env.getProvidedInterfaces());
361 container.start(external);
362 assertSame(env.getProvidedInterfaces().get(0), container
363 .getRequiredInterfaces().get(0).getProvider());
364 assertSame(env.getProvidedInterfaces().get(1), container
365 .getRequiredInterfaces().get(1).getProvider());
366 assertSame(env.getProvidedInterfaces().get(0), application
367 .getRequiredInterfaces().get(0).getProvider());
368 assertSame(env.getProvidedInterfaces().get(1), application
369 .getRequiredInterfaces().get(1).getProvider());
372 public void testOptionalRequiredInterfaceNotProvidedOptionalInternal() {
373 Application application = new Application(true);
374 Container container = new Container("top",
375 new Component[] { application }, new ProvidedInterface[0],
376 Application.required(true));
377 Environment env = new Environment();
378 container.getRequiredInterfaces().get(0).setProvider(
379 env.getProvidedInterfaces().get(0));
381 Scope external = new DefaultScope(new ProvidedInterface[0]);
382 external.publishInterface(env.getProvidedInterfaces().get(0), env
384 container.start(external);
385 assertSame(env.getProvidedInterfaces().get(0), container
386 .getRequiredInterfaces().get(0).getProvider());
387 assertNull(container.getRequiredInterfaces().get(1).getProvider());
388 assertSame(env.getProvidedInterfaces().get(0), application
389 .getRequiredInterfaces().get(0).getProvider());
390 assertNull(application.getRequiredInterfaces().get(1).getProvider());
393 public void testOptionalRequiredInterfaceProvidedMandatoryInternal() {
394 Application application = new Application();
395 Container container = new Container("top",
396 new Component[] { application }, new ProvidedInterface[0],
397 Application.required(true));
398 Environment env = new Environment();
399 container.getRequiredInterfaces().get(0).setProvider(
400 env.getProvidedInterfaces().get(0));
401 container.getRequiredInterfaces().get(1).setProvider(
402 env.getProvidedInterfaces().get(1));
406 } catch (SystemAssemblyException e) {
413 public void testSealed() {
414 final Container container = new Container("xx");
415 assertFalse(container.isSealed());
417 assertTrue(container.isSealed());
419 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
421 public void run() throws Exception {
422 container.addComponent(new Application());
424 }, SystemAssemblyException.class);
426 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
428 public void run() throws Exception {
429 container.connectRequiredProvided("x", "y", "a", "b");
431 }, SystemAssemblyException.class);
432 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
434 public void run() throws Exception {
435 container.connectExternalRequired("x", "y", "a");
437 }, SystemAssemblyException.class);
438 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
440 public void run() throws Exception {
441 container.connectExternalProvided("x", "y", "z");
443 }, SystemAssemblyException.class);
444 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
446 public void run() throws Exception {
447 container.addProvidedInterface(new DefaultProvidedInterface(
448 "xx", String.class));
450 }, SystemAssemblyException.class);
452 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
454 public void run() throws Exception {
455 container.addRequiredInterface(new DefaultRequiredInterface(
456 "xx", String.class));
458 }, SystemAssemblyException.class);
461 public void testRestriction() {
462 Environment env1 = new Environment("env1");
463 Environment env2 = new Environment("env2");
464 Application app = new Application("app");
465 Container container = new Container("top").addComponent(env1)
466 .addComponent(env2).addComponent(app);
467 container.connectRequiredProvided("app", null, "env1", null);
469 assertEquals(env1.getString(), app.getString());
470 assertEquals(env1.getInteger(), app.getInteger());
471 assertFalse(env2.getString().equals(app.getString()));
472 assertFalse(env2.getInteger().equals(app.getInteger()));
475 public void testRestrictionWithFromAndToInterfaceName() {
476 Environment env1 = new Environment("env1");
477 Environment env2 = new Environment("env2");
478 Application app = new Application("app");
479 Container container = new Container("top").addComponent(env1)
480 .addComponent(env2).addComponent(app);
481 container.connectRequiredProvided("app", app.getRequiredInterfaces()
482 .get(0).getName(), "env1", env1.getProvidedInterfaces().get(0)
484 container.connectRequiredProvided("app", app.getRequiredInterfaces()
485 .get(1).getName(), "env2", env2.getProvidedInterfaces().get(1)
488 assertEquals(env1.getString(), app.getString());
489 assertEquals(env2.getInteger(), app.getInteger());
490 assertFalse(env2.getString().equals(app.getString()));
491 assertFalse(env1.getInteger().equals(app.getInteger()));
494 public void testRestrictionWrongComponentNames() {
495 Environment env1 = new Environment("env1");
496 Environment env2 = new Environment("env2");
497 Application app = new Application("app");
498 final Container container = new Container("top").addComponent(env1)
499 .addComponent(env2).addComponent(app);
500 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
502 public void run() throws Exception {
503 container.connectRequiredProvided("app2", null, "env1", null);
505 }, SystemAssemblyException.class);
506 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
508 public void run() throws Exception {
509 container.connectRequiredProvided("app", null, "env3", null);
511 }, SystemAssemblyException.class);
514 public void testRestrictionWrongInterfaceNames() {
515 final Environment env1 = new Environment("env1");
516 Environment env2 = new Environment("env2");
517 final Application app = new Application("app");
518 final Container container = new Container("top").addComponent(env1)
519 .addComponent(env2).addComponent(app);
520 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
522 public void run() throws Exception {
523 container.connectRequiredProvided("app", app
524 .getRequiredInterfaces().get(0).getName() +
525 "xxx", "env1", null);
527 }, SystemAssemblyException.class);
528 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
530 public void run() throws Exception {
531 container.connectRequiredProvided("app", null, "env1", env1
532 .getProvidedInterfaces().get(0).getName() +
535 }, SystemAssemblyException.class);
538 public void testProvidedInDifferentScopes() {
539 // Scoping problem occurred. Externally and internally provided
540 // components clashed
541 // because unique id generation in the scope was wrong.
542 StringComponent str = new StringComponent("string");
543 Application app = new Application("app");
544 Container container = new Container("top").addComponent(str)
546 container.addRequiredInterface(new DefaultRequiredInterface("integer",
549 ProvidedInterface provided = new DefaultProvidedInterface("hallo",
551 container.getRequiredInterfaces().get(0).setProvider(provided);
553 Scope external = new DefaultScope(new ProvidedInterface[0]);
554 external.publishInterface(provided, 100);
556 Scope scope = container.start(external);
559 public void testProvidedInterfaces() {
560 Environment env = new Environment(tracker);
561 Container envcontainer = new Container("0").addComponent(env)
562 .addProvidedInterface(
563 new DefaultProvidedInterface("string", String.class))
564 .addProvidedInterface(
565 new DefaultProvidedInterface("integer", Integer.class));
566 Scope scope = envcontainer.start();
568 AssertionUtils.assertEquals(new String[] { "start.environment" },
569 tracker.getEvents(Thread.currentThread()).toArray(new String[0]));
571 envcontainer.stop(scope);
574 public void testCoupleTwoContainers() {
575 Environment env = new Environment(tracker);
576 Container envcontainer = new Container("0").addComponent(env)
577 .addProvidedInterface(
578 new DefaultProvidedInterface("string", String.class))
579 .addProvidedInterface(
580 new DefaultProvidedInterface("integer", Integer.class));
582 Application app = new Application(tracker);
583 Container appcontainer = new Container("1").addComponent(app)
584 .addRequiredInterface(
585 new DefaultRequiredInterface("string", String.class))
586 .addRequiredInterface(
587 new DefaultRequiredInterface("integer", Integer.class));
589 Container top = new Container("top");
590 top.addComponent(envcontainer).addComponent(appcontainer);
593 AssertionUtils.assertEquals(new String[] { "start.environment",
594 "start.application" }, tracker.getEvents(Thread.currentThread())
595 .toArray(new String[0]));
598 public void testNonUniqueRequiredInterface() {
599 final Container container = new Container("top");
600 container.addRequiredInterface(new DefaultRequiredInterface("i",
602 container.addRequiredInterface(new DefaultRequiredInterface("x",
604 container.addRequiredInterface(new DefaultRequiredInterface("y",
607 Application app = new Application("1");
608 container.addComponent(app);
610 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
612 public void run() throws Exception {
615 }, SystemAssemblyException.class);
617 container.connectExternalRequired("1", app.getRequiredInterfaces().get(
620 ProvidedInterface i = new DefaultProvidedInterface("i", Integer.class);
621 ProvidedInterface x = new DefaultProvidedInterface("x", String.class);
622 ProvidedInterface y = new DefaultProvidedInterface("y", String.class);
624 Scope externalScope = new DefaultScope(new ProvidedInterface[0]);
626 externalScope.publishInterface(i, 100);
627 externalScope.publishInterface(x, "x-value");
628 externalScope.publishInterface(y, "y-value");
630 container.getRequiredInterfaces().get(0).setProvider(i);
631 container.getRequiredInterfaces().get(1).setProvider(x);
632 container.getRequiredInterfaces().get(2).setProvider(y);
634 Scope runtime = container.start(externalScope);
636 assertEquals("y-value", app.getString());
639 public void testNonUniqueRequiredInterfaceWrongNames() {
640 final Container container = new Container("top");
641 container.addRequiredInterface(new DefaultRequiredInterface("i",
643 container.addRequiredInterface(new DefaultRequiredInterface("x",
645 container.addRequiredInterface(new DefaultRequiredInterface("y",
648 final Application app = new Application("1");
649 container.addComponent(app);
651 // wrong component name.
652 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
654 public void run() throws Exception {
655 container.connectExternalRequired("2", "x", "y");
657 }, SystemAssemblyException.class);
659 // Wrong interface name of component.
660 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
662 public void run() throws Exception {
663 container.connectExternalRequired("1", app
664 .getRequiredInterfaces().get(0).getName() +
667 }, SystemAssemblyException.class);
669 // Wrong external interface name of container
670 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
672 public void run() throws Exception {
673 container.connectExternalRequired("1", app
674 .getRequiredInterfaces().get(0).getName(), "z");
676 }, SystemAssemblyException.class);
679 public void testNonUniqueProvidedInterface() {
680 final Container container = new Container("top")
681 .addProvidedInterface(new DefaultProvidedInterface("external",
683 Environment env1 = new Environment("env1");
684 Environment env2 = new Environment("env2");
686 container.addComponent(env1);
687 container.addComponent(env2);
689 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
691 public void run() throws Exception {
694 }, SystemAssemblyException.class);
697 container.connectExternalProvided(container.getProvidedInterfaces()
698 .get(0).getName(), env2.getName(), env2.getProvidedInterfaces()
701 Scope scope = container.start();
703 // check the value of the provided interface of the container
704 String value = scope.getInterfaceImplementation(container
705 .getProvidedInterfaces().get(0), String.class);
706 assertNotNull(value);
707 assertEquals(value, env2.getString());
708 assertFalse(value.equals(env1.getString()));
711 public void testNonUniqueProvidedInterfaceWrongNames() {
712 final Container container = new Container("top")
713 .addProvidedInterface(new DefaultProvidedInterface("external",
715 final Environment env1 = new Environment("env1");
716 final Environment env2 = new Environment("env2");
718 container.addComponent(env1);
719 container.addComponent(env2);
721 // Wrong external provided interface name
722 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
724 public void run() throws Exception {
726 .connectExternalProvided(container.getProvidedInterfaces()
728 "xx", "env1", env1.getProvidedInterfaces().get(0)
731 }, SystemAssemblyException.class);
733 // Wrong provided interface name.
734 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
736 public void run() throws Exception {
737 container.connectExternalProvided(container
738 .getProvidedInterfaces().get(0).getName(), "env1", env1
739 .getProvidedInterfaces().get(0).getName() +
742 }, SystemAssemblyException.class);
744 // Wrong provided component
745 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
747 public void run() throws Exception {
748 container.connectExternalProvided(container
749 .getProvidedInterfaces().get(0).getName(), "env3", env1
750 .getProvidedInterfaces().get(0).getName());
752 }, SystemAssemblyException.class);
755 private static class MyMultiple implements Serializable, Runnable {