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 java.io.Serializable;
19 import java.util.ArrayList;
20 import java.util.List;
22 import junit.framework.TestCase;
24 import org.wamblee.general.Pair;
25 import org.wamblee.system.core.Component;
26 import org.wamblee.system.core.DefaultProvidedInterface;
27 import org.wamblee.system.core.DefaultRequiredInterface;
28 import org.wamblee.system.core.DefaultScope;
29 import org.wamblee.system.core.Environment;
30 import org.wamblee.system.core.ProvidedInterface;
31 import org.wamblee.system.core.RequiredInterface;
32 import org.wamblee.system.core.Scope;
33 import org.wamblee.system.core.StringComponent;
34 import org.wamblee.system.core.SystemAssemblyException;
35 import org.wamblee.test.AssertionUtils;
36 import org.wamblee.test.EventTracker;
43 public class ContainerTest extends TestCase {
44 private EventTracker<String> tracker;
47 protected void setUp() throws Exception {
49 tracker = new EventTracker<String>();
52 private List<Pair<ProvidedInterface, Component>> createProvidedInput(
53 ProvidedInterface[] aProvided, Component aProvider) {
54 List<Pair<ProvidedInterface, Component>> result = new ArrayList<Pair<ProvidedInterface, Component>>();
56 for (ProvidedInterface provided : aProvided) {
57 result.add(new Pair<ProvidedInterface, Component>(provided,
64 public void testEnvironmentApplication() {
65 Environment environment = new Environment(tracker);
66 Application application = new Application(tracker);
67 Container container = new Container("root", new Component[] {
68 environment, application }, new ProvidedInterface[0],
69 new RequiredInterface[0]);
70 Scope scope = container.start();
71 assertTrue(container.isSealed());
72 AssertionUtils.assertEquals(new String[] { "start.environment",
73 "start.application" }, tracker.getEvents(Thread.currentThread())
74 .toArray(new String[0]));
75 assertEquals(0, scope.getProvidedInterfaces().size());
77 assertEquals(environment.getString(), application.getString());
78 assertEquals(environment.getInteger(), application.getInteger());
81 public void testEnvironmentApplicationSimpleConstructor() {
82 Environment environment = new Environment(tracker);
83 Application application = new Application(tracker);
84 Container container = new Container("root").addComponent(environment)
85 .addComponent(application);
87 Scope scope = container.start();
88 AssertionUtils.assertEquals(new String[] { "start.environment",
89 "start.application" }, tracker.getEvents(Thread.currentThread())
90 .toArray(new String[0]));
91 assertEquals(0, scope.getProvidedInterfaces().size());
93 assertEquals(environment.getString(), application.getString());
94 assertEquals(environment.getInteger(), application.getInteger());
97 public void testApplicationEnvironment() {
99 Component<?> environment = new Environment();
100 Component<?> application = new Application();
101 Container container = new Container("root", new Component[] {
102 application, environment }, new ProvidedInterface[0],
103 new RequiredInterface[0]);
105 } catch (SystemAssemblyException e) {
106 // e.printStackTrace();
113 public void testComposite() {
114 Component<?> environment = new Environment(tracker);
115 Component<?> application = new Application(tracker);
116 assertEquals(0, tracker.getEventCount());
118 Container system = new Container("all", new Component[] { environment,
119 application }, new ProvidedInterface[0], new RequiredInterface[0]);
120 Scope runtime = system.start();
121 List<RequiredInterface> required = system.getRequiredInterfaces();
122 assertEquals(0, required.size());
124 List<ProvidedInterface> provided = system.getProvidedInterfaces();
125 assertEquals(0, provided.size());
127 AssertionUtils.assertEquals(new String[] { "start.environment",
128 "start.application" }, tracker.getEvents(Thread.currentThread())
129 .toArray(new String[0]));
132 system.stop(runtime);
133 AssertionUtils.assertEquals(new String[] { "stop.application",
134 "stop.environment" }, tracker.getEvents(Thread.currentThread())
135 .toArray(new String[0]));
138 public void testCompositeWithWrongProvidedInfo() {
140 Component<?> environment = new Environment();
141 Component<?> application = new Application();
142 Container system = new Container("all", new Component[] {
143 environment, application },
144 new ProvidedInterface[] { new DefaultProvidedInterface("float",
145 Float.class) }, new DefaultRequiredInterface[0]);
147 } catch (SystemAssemblyException e) {
154 public void testCompositeRequiredInterfaceNotProvided() {
156 Component<?> environment = new Environment();
157 Component<?> application = new Application();
158 Container system = new Container("all", new Component[] {
159 environment, application }, new ProvidedInterface[0],
160 new RequiredInterface[] { new DefaultRequiredInterface(
161 "string", String.class) });
163 } catch (SystemAssemblyException e) {
170 public void testCompositeWithSuperfluousRequiredInfo() {
171 Component<?> environment = new Environment();
172 Component<?> application = new Application();
173 Container system = new Container("all", new Component[] { environment,
174 application }, new ProvidedInterface[0],
175 new RequiredInterface[] { new DefaultRequiredInterface("float",
177 system.getRequiredInterfaces().get(0).setProvider(
178 new DefaultProvidedInterface("hallo", Float.class));
181 List<RequiredInterface> required = system.getRequiredInterfaces();
182 assertEquals(1, required.size());
184 List<ProvidedInterface> provided = system.getProvidedInterfaces();
185 assertEquals(0, provided.size());
188 public void testCompositeWithExternalDependencesNotProvided() {
190 Component<?> application = new Application();
192 Container system = new Container("all",
193 new Component[] { application }, new ProvidedInterface[0],
194 application.getRequiredInterfaces().toArray(
195 new RequiredInterface[0]));
197 } catch (SystemAssemblyException e) {
204 public void testDuplicateComponent() {
206 Component<?> comp1 = new Application();
207 Component<?> comp2 = new Application();
208 Container system = new Container("top");
209 system.addComponent(comp1).addComponent(comp2);
210 } catch (SystemAssemblyException e) {
217 public void testInconsistentHierarchy() {
219 Component<?> comp = new Application();
220 Container system = new Container("top").addComponent(comp);
221 Container system2 = new Container("top2").addComponent(comp);
223 ignoredVariable(system);
224 ignoredVariable(system2);
225 } catch (SystemAssemblyException e) {
232 private static void ignoredVariable(Object aObject) {
236 public void testCompositeWithExternalDependencesProvided() {
237 Component<?> environment = new Environment();
238 Component<?> application = new Application();
239 Container system = new Container("all",
240 new Component[] { application }, new ProvidedInterface[0],
241 application.getRequiredInterfaces().toArray(
242 new RequiredInterface[0]));
243 environment.start(new DefaultScope(new ProvidedInterface[0]));
244 system.getRequiredInterfaces().get(0).setProvider(
245 environment.getProvidedInterfaces().get(0));
246 system.getRequiredInterfaces().get(1).setProvider(
247 environment.getProvidedInterfaces().get(1));
251 List<RequiredInterface> required = system.getRequiredInterfaces();
252 assertEquals(2, required.size());
254 List<ProvidedInterface> provided = system.getProvidedInterfaces();
255 assertEquals(0, provided.size());
258 public void testAmbiguousInterfaces() {
260 Component<?> environment1 = new Environment();
261 Component<?> environment2 = new Environment();
262 Component<?> application = new Application();
263 Container container = new Container("root", new Component[] {
264 environment1, environment2, application },
265 new ProvidedInterface[0], new RequiredInterface[0]);
267 } catch (SystemAssemblyException e) {
274 public void testIncompleteRequirements() {
276 Component<?> application = new Application();
277 Container system = new Container("all",
278 new Component[] { application }, new ProvidedInterface[0],
279 new RequiredInterface[0]);
281 } catch (SystemAssemblyException e) {
288 public void testEnvironmentApplicationRollbackOnException()
290 Environment environment = new Environment(tracker);
291 Application application = new Application() {
293 public Object doStart(Scope aScope) {
294 throw new RuntimeException();
299 Container container = new Container("root", new Component[] {
300 environment, application }, new ProvidedInterface[0],
301 new RequiredInterface[0]);
304 } catch (RuntimeException e) {
305 AssertionUtils.assertEquals(new String[] { "start.environment",
306 "stop.environment" }, tracker.getEvents(Thread.currentThread())
307 .toArray(new String[0]));
315 public void testEnvironmentApplicationRollbackOnExceptionWithExceptionOnStop()
317 Environment environment = new Environment(tracker);
319 // Application 1 will throw an exception while stopping.
320 Application application1 = new Application("app1") {
322 public void doStop(Object aRuntime) {
323 throw new RuntimeException();
327 // application 2 will throw an exception while starting
328 Application application2 = new Application("app2") {
329 public Object doStart(Scope aScope) {
330 throw new RuntimeException();
335 Container container = new Container("root", new Component[] {
336 environment, application1, application2 },
337 new ProvidedInterface[0], new RequiredInterface[0]);
340 } catch (RuntimeException e) {
341 AssertionUtils.assertEquals(new String[] { "start.environment",
342 "stop.environment" }, tracker.getEvents(Thread.currentThread())
343 .toArray(new String[0]));
351 public void testOptionalRequiredInterfaceProvidedOptionalInternal() {
352 Application application = new Application(true);
353 Container container = new Container("top",
354 new Component[] { application }, new ProvidedInterface[0],
355 Application.required(true));
356 Environment env = new Environment();
357 container.getRequiredInterfaces().get(0).setProvider(
358 env.getProvidedInterfaces().get(0));
359 container.getRequiredInterfaces().get(1).setProvider(
360 env.getProvidedInterfaces().get(1));
362 Scope external = new DefaultScope(env.getProvidedInterfaces());
365 container.start(external);
366 assertSame(env.getProvidedInterfaces().get(0), container
367 .getRequiredInterfaces().get(0).getProvider());
368 assertSame(env.getProvidedInterfaces().get(1), container
369 .getRequiredInterfaces().get(1).getProvider());
370 assertSame(env.getProvidedInterfaces().get(0), application
371 .getRequiredInterfaces().get(0).getProvider());
372 assertSame(env.getProvidedInterfaces().get(1), application
373 .getRequiredInterfaces().get(1).getProvider());
376 public void testOptionalRequiredInterfaceNotProvidedOptionalInternal() {
377 Application application = new Application(true);
378 Container container = new Container("top",
379 new Component[] { application }, new ProvidedInterface[0],
380 Application.required(true));
381 Environment env = new Environment();
382 container.getRequiredInterfaces().get(0).setProvider(
383 env.getProvidedInterfaces().get(0));
385 Scope external = new DefaultScope(new ProvidedInterface[0]);
386 external.publishInterface(env.getProvidedInterfaces().get(0), env
388 container.start(external);
389 assertSame(env.getProvidedInterfaces().get(0), container
390 .getRequiredInterfaces().get(0).getProvider());
391 assertNull(container.getRequiredInterfaces().get(1).getProvider());
392 assertSame(env.getProvidedInterfaces().get(0), application
393 .getRequiredInterfaces().get(0).getProvider());
394 assertNull(application.getRequiredInterfaces().get(1).getProvider());
397 public void testOptionalRequiredInterfaceProvidedMandatoryInternal() {
398 Application application = new Application();
399 Container container = new Container("top",
400 new Component[] { application }, new ProvidedInterface[0],
401 Application.required(true));
402 Environment env = new Environment();
403 container.getRequiredInterfaces().get(0).setProvider(
404 env.getProvidedInterfaces().get(0));
405 container.getRequiredInterfaces().get(1).setProvider(
406 env.getProvidedInterfaces().get(1));
410 } catch (SystemAssemblyException e) {
417 public void testSealed() {
418 final Container container = new Container("xx");
419 assertFalse(container.isSealed());
421 assertTrue(container.isSealed());
423 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
425 public void run() throws Exception {
426 container.addComponent(new Application());
428 }, SystemAssemblyException.class);
430 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
432 public void run() throws Exception {
433 container.connectRequiredProvided("x", "y", "a", "b");
435 }, SystemAssemblyException.class);
436 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
438 public void run() throws Exception {
439 container.connectExternalRequired("x", "y", "a");
441 }, SystemAssemblyException.class);
442 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
444 public void run() throws Exception {
445 container.connectExternalProvided("x", "y", "z");
447 }, SystemAssemblyException.class);
448 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
450 public void run() throws Exception {
451 container.addProvidedInterface(new DefaultProvidedInterface(
452 "xx", String.class));
454 }, SystemAssemblyException.class);
456 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
458 public void run() throws Exception {
459 container.addRequiredInterface(new DefaultRequiredInterface(
460 "xx", String.class));
462 }, SystemAssemblyException.class);
465 public void testRestriction() {
466 Environment env1 = new Environment("env1");
467 Environment env2 = new Environment("env2");
468 Application app = new Application("app");
469 Container container = new Container("top").addComponent(env1)
470 .addComponent(env2).addComponent(app);
471 container.connectRequiredProvided("app", null, "env1", null);
473 assertEquals(env1.getString(), app.getString());
474 assertEquals(env1.getInteger(), app.getInteger());
475 assertFalse(env2.getString().equals(app.getString()));
476 assertFalse(env2.getInteger().equals(app.getInteger()));
479 public void testRestrictionWithFromAndToInterfaceName() {
480 Environment env1 = new Environment("env1");
481 Environment env2 = new Environment("env2");
482 Application app = new Application("app");
483 Container container = new Container("top").addComponent(env1)
484 .addComponent(env2).addComponent(app);
485 container.connectRequiredProvided("app", app.getRequiredInterfaces()
486 .get(0).getName(), "env1", env1.getProvidedInterfaces().get(0)
488 container.connectRequiredProvided("app", app.getRequiredInterfaces()
489 .get(1).getName(), "env2", env2.getProvidedInterfaces().get(1)
492 assertEquals(env1.getString(), app.getString());
493 assertEquals(env2.getInteger(), app.getInteger());
494 assertFalse(env2.getString().equals(app.getString()));
495 assertFalse(env1.getInteger().equals(app.getInteger()));
498 public void testRestrictionWrongComponentNames() {
499 Environment env1 = new Environment("env1");
500 Environment env2 = new Environment("env2");
501 Application app = new Application("app");
502 final Container container = new Container("top").addComponent(env1)
503 .addComponent(env2).addComponent(app);
504 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
506 public void run() throws Exception {
507 container.connectRequiredProvided("app2", null, "env1", null);
509 }, SystemAssemblyException.class);
510 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
512 public void run() throws Exception {
513 container.connectRequiredProvided("app", null, "env3", null);
515 }, SystemAssemblyException.class);
518 public void testRestrictionWrongInterfaceNames() {
519 final Environment env1 = new Environment("env1");
520 Environment env2 = new Environment("env2");
521 final Application app = new Application("app");
522 final Container container = new Container("top").addComponent(env1)
523 .addComponent(env2).addComponent(app);
524 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
526 public void run() throws Exception {
527 container.connectRequiredProvided("app", app
528 .getRequiredInterfaces().get(0).getName() +
529 "xxx", "env1", null);
531 }, SystemAssemblyException.class);
532 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
534 public void run() throws Exception {
535 container.connectRequiredProvided("app", null, "env1", env1
536 .getProvidedInterfaces().get(0).getName() +
539 }, SystemAssemblyException.class);
542 public void testProvidedInDifferentScopes() {
543 // Scoping problem occurred. Externally and internally provided
544 // components clashed
545 // because unique id generation in the scope was wrong.
546 StringComponent str = new StringComponent("string");
547 Application app = new Application("app");
548 Container container = new Container("top").addComponent(str)
550 container.addRequiredInterface(new DefaultRequiredInterface("integer",
553 ProvidedInterface provided = new DefaultProvidedInterface("hallo",
555 container.getRequiredInterfaces().get(0).setProvider(provided);
557 Scope external = new DefaultScope(new ProvidedInterface[0]);
558 external.publishInterface(provided, 100);
560 container.start(external);
563 public void testProvidedInterfaces() {
564 Environment env = new Environment(tracker);
565 Container envcontainer = new Container("0").addComponent(env)
566 .addProvidedInterface(
567 new DefaultProvidedInterface("string", String.class))
568 .addProvidedInterface(
569 new DefaultProvidedInterface("integer", Integer.class));
570 Scope scope = envcontainer.start();
572 AssertionUtils.assertEquals(new String[] { "start.environment" },
573 tracker.getEvents(Thread.currentThread()).toArray(new String[0]));
575 envcontainer.stop(scope);
578 public void testCoupleTwoContainers() {
579 Environment env = new Environment(tracker);
580 Container envcontainer = new Container("0").addComponent(env)
581 .addProvidedInterface(
582 new DefaultProvidedInterface("string", String.class))
583 .addProvidedInterface(
584 new DefaultProvidedInterface("integer", Integer.class));
586 Application app = new Application(tracker);
587 Container appcontainer = new Container("1").addComponent(app)
588 .addRequiredInterface(
589 new DefaultRequiredInterface("string", String.class))
590 .addRequiredInterface(
591 new DefaultRequiredInterface("integer", Integer.class));
593 Container top = new Container("top");
594 top.addComponent(envcontainer).addComponent(appcontainer);
597 AssertionUtils.assertEquals(new String[] { "start.environment",
598 "start.application" }, tracker.getEvents(Thread.currentThread())
599 .toArray(new String[0]));
602 public void testNonUniqueRequiredInterface() {
603 final Container container = new Container("top");
604 container.addRequiredInterface(new DefaultRequiredInterface("i",
606 container.addRequiredInterface(new DefaultRequiredInterface("x",
608 container.addRequiredInterface(new DefaultRequiredInterface("y",
611 Application app = new Application("1");
612 container.addComponent(app);
614 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
616 public void run() throws Exception {
619 }, SystemAssemblyException.class);
621 container.connectExternalRequired("1", app.getRequiredInterfaces().get(
624 ProvidedInterface i = new DefaultProvidedInterface("i", Integer.class);
625 ProvidedInterface x = new DefaultProvidedInterface("x", String.class);
626 ProvidedInterface y = new DefaultProvidedInterface("y", String.class);
628 Scope externalScope = new DefaultScope(new ProvidedInterface[0]);
630 externalScope.publishInterface(i, 100);
631 externalScope.publishInterface(x, "x-value");
632 externalScope.publishInterface(y, "y-value");
634 container.getRequiredInterfaces().get(0).setProvider(i);
635 container.getRequiredInterfaces().get(1).setProvider(x);
636 container.getRequiredInterfaces().get(2).setProvider(y);
638 container.start(externalScope);
640 assertEquals("y-value", app.getString());
643 public void testNonUniqueRequiredInterfaceWrongNames() {
644 final Container container = new Container("top");
645 container.addRequiredInterface(new DefaultRequiredInterface("i",
647 container.addRequiredInterface(new DefaultRequiredInterface("x",
649 container.addRequiredInterface(new DefaultRequiredInterface("y",
652 final Application app = new Application("1");
653 container.addComponent(app);
655 // wrong component name.
656 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
658 public void run() throws Exception {
659 container.connectExternalRequired("2", "x", "y");
661 }, SystemAssemblyException.class);
663 // Wrong interface name of component.
664 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
666 public void run() throws Exception {
667 container.connectExternalRequired("1", app
668 .getRequiredInterfaces().get(0).getName() +
671 }, SystemAssemblyException.class);
673 // Wrong external interface name of container
674 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
676 public void run() throws Exception {
677 container.connectExternalRequired("1", app
678 .getRequiredInterfaces().get(0).getName(), "z");
680 }, SystemAssemblyException.class);
683 public void testNonUniqueProvidedInterface() {
684 final Container container = new Container("top")
685 .addProvidedInterface(new DefaultProvidedInterface("external",
687 Environment env1 = new Environment("env1");
688 Environment env2 = new Environment("env2");
690 container.addComponent(env1);
691 container.addComponent(env2);
693 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
695 public void run() throws Exception {
698 }, SystemAssemblyException.class);
701 container.connectExternalProvided(container.getProvidedInterfaces()
702 .get(0).getName(), env2.getName(), env2.getProvidedInterfaces()
705 Scope scope = container.start();
707 // check the value of the provided interface of the container
708 String value = scope.getInterfaceImplementation(container
709 .getProvidedInterfaces().get(0), String.class);
710 assertNotNull(value);
711 assertEquals(value, env2.getString());
712 assertFalse(value.equals(env1.getString()));
715 public void testNonUniqueProvidedInterfaceWrongNames() {
716 final Container container = new Container("top")
717 .addProvidedInterface(new DefaultProvidedInterface("external",
719 final Environment env1 = new Environment("env1");
720 final Environment env2 = new Environment("env2");
722 container.addComponent(env1);
723 container.addComponent(env2);
725 // Wrong external provided interface name
726 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
728 public void run() throws Exception {
730 .connectExternalProvided(container.getProvidedInterfaces()
732 "xx", "env1", env1.getProvidedInterfaces().get(0)
735 }, SystemAssemblyException.class);
737 // Wrong provided interface name.
738 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
740 public void run() throws Exception {
741 container.connectExternalProvided(container
742 .getProvidedInterfaces().get(0).getName(), "env1", env1
743 .getProvidedInterfaces().get(0).getName() +
746 }, SystemAssemblyException.class);
748 // Wrong provided component
749 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
751 public void run() throws Exception {
752 container.connectExternalProvided(container
753 .getProvidedInterfaces().get(0).getName(), "env3", env1
754 .getProvidedInterfaces().get(0).getName());
756 }, SystemAssemblyException.class);
759 private static class MyMultiple implements Serializable, Runnable {