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.junit.internal.requests.IgnoredClassRunner;
21 import org.wamblee.general.Pair;
23 import org.wamblee.system.core.Component;
24 import org.wamblee.system.core.DefaultProvidedInterface;
25 import org.wamblee.system.core.DefaultRequiredInterface;
26 import org.wamblee.system.core.DefaultScope;
27 import org.wamblee.system.core.Environment;
28 import org.wamblee.system.core.ProvidedInterface;
29 import org.wamblee.system.core.RequiredInterface;
30 import org.wamblee.system.core.Scope;
31 import org.wamblee.system.core.StringComponent;
32 import org.wamblee.system.core.SystemAssemblyException;
34 import org.wamblee.test.AssertionUtils;
35 import org.wamblee.test.EventTracker;
37 import java.io.Serializable;
39 import java.util.ArrayList;
40 import java.util.List;
47 public class ContainerTest extends TestCase {
48 private EventTracker<String> tracker;
51 protected void setUp() throws Exception {
53 tracker = new EventTracker<String>();
56 private List<Pair<ProvidedInterface, Component>> createProvidedInput(
57 ProvidedInterface[] aProvided, Component aProvider) {
58 List<Pair<ProvidedInterface, Component>> result = new ArrayList<Pair<ProvidedInterface, Component>>();
60 for (ProvidedInterface provided : aProvided) {
61 result.add(new Pair<ProvidedInterface, Component>(provided,
68 public void testEnvironmentApplication() {
69 Environment environment = new Environment(tracker);
70 Application application = new Application(tracker);
71 Container container = new Container("root", new Component[] {
72 environment, application }, new ProvidedInterface[0],
73 new RequiredInterface[0]);
74 Scope scope = container.start();
75 assertTrue(container.isSealed());
76 AssertionUtils.assertEquals(new String[] { "start.environment",
77 "start.application" }, tracker.getEvents(Thread.currentThread())
78 .toArray(new String[0]));
79 assertEquals(0, scope.getProvidedInterfaces().size());
81 assertEquals(environment.getString(), application.getString());
82 assertEquals(environment.getInteger(), application.getInteger());
85 public void testEnvironmentApplicationSimpleConstructor() {
86 Environment environment = new Environment(tracker);
87 Application application = new Application(tracker);
88 Container container = new Container("root").addComponent(environment)
89 .addComponent(application);
91 Scope scope = container.start();
92 AssertionUtils.assertEquals(new String[] { "start.environment",
93 "start.application" }, tracker.getEvents(Thread.currentThread())
94 .toArray(new String[0]));
95 assertEquals(0, scope.getProvidedInterfaces().size());
97 assertEquals(environment.getString(), application.getString());
98 assertEquals(environment.getInteger(), application.getInteger());
101 public void testApplicationEnvironment() {
103 Component<?> environment = new Environment();
104 Component<?> application = new Application();
105 Container container = new Container("root", new Component[] {
106 application, environment }, new ProvidedInterface[0],
107 new RequiredInterface[0]);
109 } catch (SystemAssemblyException e) {
110 // e.printStackTrace();
117 public void testComposite() {
118 Component<?> environment = new Environment(tracker);
119 Component<?> application = new Application(tracker);
120 assertEquals(0, tracker.getEventCount());
122 Container system = new Container("all", new Component[] { environment,
123 application }, new ProvidedInterface[0], new RequiredInterface[0]);
124 Scope runtime = system.start();
125 List<RequiredInterface> required = system.getRequiredInterfaces();
126 assertEquals(0, required.size());
128 List<ProvidedInterface> provided = system.getProvidedInterfaces();
129 assertEquals(0, provided.size());
131 AssertionUtils.assertEquals(new String[] { "start.environment",
132 "start.application" }, tracker.getEvents(Thread.currentThread())
133 .toArray(new String[0]));
136 system.stop(runtime);
137 AssertionUtils.assertEquals(new String[] { "stop.application",
138 "stop.environment" }, tracker.getEvents(Thread.currentThread())
139 .toArray(new String[0]));
142 public void testCompositeWithWrongProvidedInfo() {
144 Component<?> environment = new Environment();
145 Component<?> application = new Application();
146 Container system = new Container("all", new Component[] {
147 environment, application },
148 new ProvidedInterface[] { new DefaultProvidedInterface("float",
149 Float.class) }, new DefaultRequiredInterface[0]);
151 } catch (SystemAssemblyException e) {
158 public void testCompositeRequiredInterfaceNotProvided() {
160 Component<?> environment = new Environment();
161 Component<?> application = new Application();
162 Container system = new Container("all", new Component[] {
163 environment, application }, new ProvidedInterface[0],
164 new RequiredInterface[] { new DefaultRequiredInterface(
165 "string", String.class) });
167 } catch (SystemAssemblyException e) {
174 public void testCompositeWithSuperfluousRequiredInfo() {
175 Component<?> environment = new Environment();
176 Component<?> application = new Application();
177 Container system = new Container("all", new Component[] { environment,
178 application }, new ProvidedInterface[0],
179 new RequiredInterface[] { new DefaultRequiredInterface("float",
181 system.getRequiredInterfaces().get(0).setProvider(
182 new DefaultProvidedInterface("hallo", Float.class));
185 List<RequiredInterface> required = system.getRequiredInterfaces();
186 assertEquals(1, required.size());
188 List<ProvidedInterface> provided = system.getProvidedInterfaces();
189 assertEquals(0, provided.size());
192 public void testCompositeWithExternalDependencesNotProvided() {
194 Component<?> application = new Application();
196 Container system = new Container("all",
197 new Component[] { application }, new ProvidedInterface[0],
198 application.getRequiredInterfaces().toArray(
199 new RequiredInterface[0]));
201 } catch (SystemAssemblyException e) {
208 public void testDuplicateComponent() {
210 Component<?> comp1 = new Application();
211 Component<?> comp2 = new Application();
212 Container system = new Container("top");
213 system.addComponent(comp1).addComponent(comp2);
214 } catch (SystemAssemblyException e) {
221 public void testInconsistentHierarchy() {
223 Component<?> comp = new Application();
224 Container system = new Container("top").addComponent(comp);
225 Container system2 = new Container("top2").addComponent(comp);
227 ignoredVariable(system);
228 ignoredVariable(system2);
229 } catch (SystemAssemblyException e) {
236 private static void ignoredVariable(Object aObject) {
240 public void testCompositeWithExternalDependencesProvided() {
241 Component<?> environment = new Environment();
242 Component<?> application = new Application();
243 Container system = new Container("all",
244 new Component[] { application }, new ProvidedInterface[0],
245 application.getRequiredInterfaces().toArray(
246 new RequiredInterface[0]));
247 environment.start(new DefaultScope(new ProvidedInterface[0]));
248 system.getRequiredInterfaces().get(0).setProvider(
249 environment.getProvidedInterfaces().get(0));
250 system.getRequiredInterfaces().get(1).setProvider(
251 environment.getProvidedInterfaces().get(1));
255 List<RequiredInterface> required = system.getRequiredInterfaces();
256 assertEquals(2, required.size());
258 List<ProvidedInterface> provided = system.getProvidedInterfaces();
259 assertEquals(0, provided.size());
262 public void testAmbiguousInterfaces() {
264 Component<?> environment1 = new Environment();
265 Component<?> environment2 = new Environment();
266 Component<?> application = new Application();
267 Container container = new Container("root", new Component[] {
268 environment1, environment2, application },
269 new ProvidedInterface[0], new RequiredInterface[0]);
271 } catch (SystemAssemblyException e) {
278 public void testIncompleteRequirements() {
280 Component<?> application = new Application();
281 Container system = new Container("all",
282 new Component[] { application }, new ProvidedInterface[0],
283 new RequiredInterface[0]);
285 } catch (SystemAssemblyException e) {
292 public void testEnvironmentApplicationRollbackOnException()
294 Environment environment = new Environment(tracker);
295 Application application = new Application() {
297 public Object doStart(Scope aScope) {
298 throw new RuntimeException();
303 Container container = new Container("root", new Component[] {
304 environment, application }, new ProvidedInterface[0],
305 new RequiredInterface[0]);
308 } catch (RuntimeException e) {
309 AssertionUtils.assertEquals(new String[] { "start.environment",
310 "stop.environment" }, tracker.getEvents(Thread.currentThread())
311 .toArray(new String[0]));
319 public void testEnvironmentApplicationRollbackOnExceptionWithExceptionOnStop()
321 Environment environment = new Environment(tracker);
323 // Application 1 will throw an exception while stopping.
324 Application application1 = new Application("app1") {
326 public void doStop(Object aRuntime) {
327 throw new RuntimeException();
331 // application 2 will throw an exception while starting
332 Application application2 = new Application("app2") {
333 public Object doStart(Scope aScope) {
334 throw new RuntimeException();
339 Container container = new Container("root", new Component[] {
340 environment, application1, application2 },
341 new ProvidedInterface[0], new RequiredInterface[0]);
344 } catch (RuntimeException e) {
345 AssertionUtils.assertEquals(new String[] { "start.environment",
346 "stop.environment" }, tracker.getEvents(Thread.currentThread())
347 .toArray(new String[0]));
355 public void testOptionalRequiredInterfaceProvidedOptionalInternal() {
356 Application application = new Application(true);
357 Container container = new Container("top",
358 new Component[] { application }, new ProvidedInterface[0],
359 Application.required(true));
360 Environment env = new Environment();
361 container.getRequiredInterfaces().get(0).setProvider(
362 env.getProvidedInterfaces().get(0));
363 container.getRequiredInterfaces().get(1).setProvider(
364 env.getProvidedInterfaces().get(1));
366 Scope external = new DefaultScope(env.getProvidedInterfaces());
369 container.start(external);
370 assertSame(env.getProvidedInterfaces().get(0), container
371 .getRequiredInterfaces().get(0).getProvider());
372 assertSame(env.getProvidedInterfaces().get(1), container
373 .getRequiredInterfaces().get(1).getProvider());
374 assertSame(env.getProvidedInterfaces().get(0), application
375 .getRequiredInterfaces().get(0).getProvider());
376 assertSame(env.getProvidedInterfaces().get(1), application
377 .getRequiredInterfaces().get(1).getProvider());
380 public void testOptionalRequiredInterfaceNotProvidedOptionalInternal() {
381 Application application = new Application(true);
382 Container container = new Container("top",
383 new Component[] { application }, new ProvidedInterface[0],
384 Application.required(true));
385 Environment env = new Environment();
386 container.getRequiredInterfaces().get(0).setProvider(
387 env.getProvidedInterfaces().get(0));
389 Scope external = new DefaultScope(new ProvidedInterface[0]);
390 external.publishInterface(env.getProvidedInterfaces().get(0), env
392 container.start(external);
393 assertSame(env.getProvidedInterfaces().get(0), container
394 .getRequiredInterfaces().get(0).getProvider());
395 assertNull(container.getRequiredInterfaces().get(1).getProvider());
396 assertSame(env.getProvidedInterfaces().get(0), application
397 .getRequiredInterfaces().get(0).getProvider());
398 assertNull(application.getRequiredInterfaces().get(1).getProvider());
401 public void testOptionalRequiredInterfaceProvidedMandatoryInternal() {
402 Application application = new Application();
403 Container container = new Container("top",
404 new Component[] { application }, new ProvidedInterface[0],
405 Application.required(true));
406 Environment env = new Environment();
407 container.getRequiredInterfaces().get(0).setProvider(
408 env.getProvidedInterfaces().get(0));
409 container.getRequiredInterfaces().get(1).setProvider(
410 env.getProvidedInterfaces().get(1));
414 } catch (SystemAssemblyException e) {
421 public void testSealed() {
422 final Container container = new Container("xx");
423 assertFalse(container.isSealed());
425 assertTrue(container.isSealed());
427 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
429 public void run() throws Exception {
430 container.addComponent(new Application());
432 }, SystemAssemblyException.class);
434 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
436 public void run() throws Exception {
437 container.connectRequiredProvided("x", "y", "a", "b");
439 }, SystemAssemblyException.class);
440 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
442 public void run() throws Exception {
443 container.connectExternalRequired("x", "y", "a");
445 }, SystemAssemblyException.class);
446 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
448 public void run() throws Exception {
449 container.connectExternalProvided("x", "y", "z");
451 }, SystemAssemblyException.class);
452 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
454 public void run() throws Exception {
455 container.addProvidedInterface(new DefaultProvidedInterface(
456 "xx", String.class));
458 }, SystemAssemblyException.class);
460 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
462 public void run() throws Exception {
463 container.addRequiredInterface(new DefaultRequiredInterface(
464 "xx", String.class));
466 }, SystemAssemblyException.class);
469 public void testRestriction() {
470 Environment env1 = new Environment("env1");
471 Environment env2 = new Environment("env2");
472 Application app = new Application("app");
473 Container container = new Container("top").addComponent(env1)
474 .addComponent(env2).addComponent(app);
475 container.connectRequiredProvided("app", null, "env1", null);
477 assertEquals(env1.getString(), app.getString());
478 assertEquals(env1.getInteger(), app.getInteger());
479 assertFalse(env2.getString().equals(app.getString()));
480 assertFalse(env2.getInteger().equals(app.getInteger()));
483 public void testRestrictionWithFromAndToInterfaceName() {
484 Environment env1 = new Environment("env1");
485 Environment env2 = new Environment("env2");
486 Application app = new Application("app");
487 Container container = new Container("top").addComponent(env1)
488 .addComponent(env2).addComponent(app);
489 container.connectRequiredProvided("app", app.getRequiredInterfaces()
490 .get(0).getName(), "env1", env1.getProvidedInterfaces().get(0)
492 container.connectRequiredProvided("app", app.getRequiredInterfaces()
493 .get(1).getName(), "env2", env2.getProvidedInterfaces().get(1)
496 assertEquals(env1.getString(), app.getString());
497 assertEquals(env2.getInteger(), app.getInteger());
498 assertFalse(env2.getString().equals(app.getString()));
499 assertFalse(env1.getInteger().equals(app.getInteger()));
502 public void testRestrictionWrongComponentNames() {
503 Environment env1 = new Environment("env1");
504 Environment env2 = new Environment("env2");
505 Application app = new Application("app");
506 final Container container = new Container("top").addComponent(env1)
507 .addComponent(env2).addComponent(app);
508 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
510 public void run() throws Exception {
511 container.connectRequiredProvided("app2", null, "env1", null);
513 }, SystemAssemblyException.class);
514 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
516 public void run() throws Exception {
517 container.connectRequiredProvided("app", null, "env3", null);
519 }, SystemAssemblyException.class);
522 public void testRestrictionWrongInterfaceNames() {
523 final Environment env1 = new Environment("env1");
524 Environment env2 = new Environment("env2");
525 final Application app = new Application("app");
526 final Container container = new Container("top").addComponent(env1)
527 .addComponent(env2).addComponent(app);
528 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
530 public void run() throws Exception {
531 container.connectRequiredProvided("app", app
532 .getRequiredInterfaces().get(0).getName() +
533 "xxx", "env1", null);
535 }, SystemAssemblyException.class);
536 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
538 public void run() throws Exception {
539 container.connectRequiredProvided("app", null, "env1", env1
540 .getProvidedInterfaces().get(0).getName() +
543 }, SystemAssemblyException.class);
546 public void testProvidedInDifferentScopes() {
547 // Scoping problem occurred. Externally and internally provided
548 // components clashed
549 // because unique id generation in the scope was wrong.
550 StringComponent str = new StringComponent("string");
551 Application app = new Application("app");
552 Container container = new Container("top").addComponent(str)
554 container.addRequiredInterface(new DefaultRequiredInterface("integer",
557 ProvidedInterface provided = new DefaultProvidedInterface("hallo",
559 container.getRequiredInterfaces().get(0).setProvider(provided);
561 Scope external = new DefaultScope(new ProvidedInterface[0]);
562 external.publishInterface(provided, 100);
564 container.start(external);
567 public void testProvidedInterfaces() {
568 Environment env = new Environment(tracker);
569 Container envcontainer = new Container("0").addComponent(env)
570 .addProvidedInterface(
571 new DefaultProvidedInterface("string", String.class))
572 .addProvidedInterface(
573 new DefaultProvidedInterface("integer", Integer.class));
574 Scope scope = envcontainer.start();
576 AssertionUtils.assertEquals(new String[] { "start.environment" },
577 tracker.getEvents(Thread.currentThread()).toArray(new String[0]));
579 envcontainer.stop(scope);
582 public void testCoupleTwoContainers() {
583 Environment env = new Environment(tracker);
584 Container envcontainer = new Container("0").addComponent(env)
585 .addProvidedInterface(
586 new DefaultProvidedInterface("string", String.class))
587 .addProvidedInterface(
588 new DefaultProvidedInterface("integer", Integer.class));
590 Application app = new Application(tracker);
591 Container appcontainer = new Container("1").addComponent(app)
592 .addRequiredInterface(
593 new DefaultRequiredInterface("string", String.class))
594 .addRequiredInterface(
595 new DefaultRequiredInterface("integer", Integer.class));
597 Container top = new Container("top");
598 top.addComponent(envcontainer).addComponent(appcontainer);
601 AssertionUtils.assertEquals(new String[] { "start.environment",
602 "start.application" }, tracker.getEvents(Thread.currentThread())
603 .toArray(new String[0]));
606 public void testNonUniqueRequiredInterface() {
607 final Container container = new Container("top");
608 container.addRequiredInterface(new DefaultRequiredInterface("i",
610 container.addRequiredInterface(new DefaultRequiredInterface("x",
612 container.addRequiredInterface(new DefaultRequiredInterface("y",
615 Application app = new Application("1");
616 container.addComponent(app);
618 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
620 public void run() throws Exception {
623 }, SystemAssemblyException.class);
625 container.connectExternalRequired("1", app.getRequiredInterfaces().get(
628 ProvidedInterface i = new DefaultProvidedInterface("i", Integer.class);
629 ProvidedInterface x = new DefaultProvidedInterface("x", String.class);
630 ProvidedInterface y = new DefaultProvidedInterface("y", String.class);
632 Scope externalScope = new DefaultScope(new ProvidedInterface[0]);
634 externalScope.publishInterface(i, 100);
635 externalScope.publishInterface(x, "x-value");
636 externalScope.publishInterface(y, "y-value");
638 container.getRequiredInterfaces().get(0).setProvider(i);
639 container.getRequiredInterfaces().get(1).setProvider(x);
640 container.getRequiredInterfaces().get(2).setProvider(y);
642 container.start(externalScope);
644 assertEquals("y-value", app.getString());
647 public void testNonUniqueRequiredInterfaceWrongNames() {
648 final Container container = new Container("top");
649 container.addRequiredInterface(new DefaultRequiredInterface("i",
651 container.addRequiredInterface(new DefaultRequiredInterface("x",
653 container.addRequiredInterface(new DefaultRequiredInterface("y",
656 final Application app = new Application("1");
657 container.addComponent(app);
659 // wrong component name.
660 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
662 public void run() throws Exception {
663 container.connectExternalRequired("2", "x", "y");
665 }, SystemAssemblyException.class);
667 // Wrong interface name of component.
668 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
670 public void run() throws Exception {
671 container.connectExternalRequired("1", app
672 .getRequiredInterfaces().get(0).getName() +
675 }, SystemAssemblyException.class);
677 // Wrong external interface name of container
678 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
680 public void run() throws Exception {
681 container.connectExternalRequired("1", app
682 .getRequiredInterfaces().get(0).getName(), "z");
684 }, SystemAssemblyException.class);
687 public void testNonUniqueProvidedInterface() {
688 final Container container = new Container("top")
689 .addProvidedInterface(new DefaultProvidedInterface("external",
691 Environment env1 = new Environment("env1");
692 Environment env2 = new Environment("env2");
694 container.addComponent(env1);
695 container.addComponent(env2);
697 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
699 public void run() throws Exception {
702 }, SystemAssemblyException.class);
705 container.connectExternalProvided(container.getProvidedInterfaces()
706 .get(0).getName(), env2.getName(), env2.getProvidedInterfaces()
709 Scope scope = container.start();
711 // check the value of the provided interface of the container
712 String value = scope.getInterfaceImplementation(container
713 .getProvidedInterfaces().get(0), String.class);
714 assertNotNull(value);
715 assertEquals(value, env2.getString());
716 assertFalse(value.equals(env1.getString()));
719 public void testNonUniqueProvidedInterfaceWrongNames() {
720 final Container container = new Container("top")
721 .addProvidedInterface(new DefaultProvidedInterface("external",
723 final Environment env1 = new Environment("env1");
724 final Environment env2 = new Environment("env2");
726 container.addComponent(env1);
727 container.addComponent(env2);
729 // Wrong external provided interface name
730 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
732 public void run() throws Exception {
734 .connectExternalProvided(container.getProvidedInterfaces()
736 "xx", "env1", env1.getProvidedInterfaces().get(0)
739 }, SystemAssemblyException.class);
741 // Wrong provided interface name.
742 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
744 public void run() throws Exception {
745 container.connectExternalProvided(container
746 .getProvidedInterfaces().get(0).getName(), "env1", env1
747 .getProvidedInterfaces().get(0).getName() +
750 }, SystemAssemblyException.class);
752 // Wrong provided component
753 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
755 public void run() throws Exception {
756 container.connectExternalProvided(container
757 .getProvidedInterfaces().get(0).getName(), "env3", env1
758 .getProvidedInterfaces().get(0).getName());
760 }, SystemAssemblyException.class);
763 private static class MyMultiple implements Serializable, Runnable {