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 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;
38 public class ContainerTest extends TestCase {
40 private EventTracker<String> _tracker;
43 protected void setUp() throws Exception {
45 _tracker = new EventTracker<String>();
48 private static class MyMultiple implements Serializable, Runnable {
55 private List<Pair<ProvidedInterface, Component>> createProvidedInput(
56 ProvidedInterface[] aProvided, Component aProvider) {
57 List<Pair<ProvidedInterface, Component>> result = new ArrayList<Pair<ProvidedInterface, Component>>();
58 for (ProvidedInterface provided : aProvided) {
59 result.add(new Pair<ProvidedInterface, Component>(provided,
65 public void testEnvironmentApplication() {
66 Environment environment = new Environment(_tracker);
67 Application application = new Application(_tracker);
68 Container container = new Container("root", new Component[] {
69 environment, application }, new ProvidedInterface[0],
70 new RequiredInterface[0]);
71 Scope scope = container.start();
72 assertTrue(container.isSealed());
73 AssertionUtils.assertEquals(new String[] { "start.environment",
74 "start.application" }, _tracker.getEvents(
75 Thread.currentThread()).toArray(new String[0]));
76 assertEquals(0, scope.getProvidedInterfaces().size());
78 assertEquals(environment.getString(), application.getString());
79 assertEquals(environment.getInteger(), application.getInteger());
83 public void testEnvironmentApplicationSimpleConstructor() {
84 Environment environment = new Environment(_tracker);
85 Application application = new Application(_tracker);
86 Container container = new Container("root").addComponent(environment)
87 .addComponent(application);
89 Scope scope = container.start();
90 AssertionUtils.assertEquals(new String[] { "start.environment",
91 "start.application" }, _tracker.getEvents(
92 Thread.currentThread()).toArray(new String[0]));
93 assertEquals(0, scope.getProvidedInterfaces().size());
95 assertEquals(environment.getString(), application.getString());
96 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();
115 public void testComposite() {
116 Component<?> environment = new Environment(_tracker);
117 Component<?> application = new Application(_tracker);
118 assertEquals(0, _tracker.getEventCount());
120 Container system = new Container("all", new Component[] { environment,
121 application }, new ProvidedInterface[0],
122 new RequiredInterface[0]);
123 Scope runtime = system.start();
124 List<RequiredInterface> required = system.getRequiredInterfaces();
125 assertEquals(0, required.size());
126 List<ProvidedInterface> provided = system.getProvidedInterfaces();
127 assertEquals(0, provided.size());
129 AssertionUtils.assertEquals(new String[] { "start.environment",
130 "start.application" }, _tracker.getEvents(
131 Thread.currentThread()).toArray(new String[0]));
134 system.stop(runtime);
135 AssertionUtils.assertEquals(new String[] { "stop.application",
136 "stop.environment" }, _tracker
137 .getEvents(Thread.currentThread()).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(
148 "float", Float.class) },
149 new DefaultRequiredInterface[0]);
151 } 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) {
172 public void testCompositeWithSuperfluousRequiredInfo() {
173 Component<?> environment = new Environment();
174 Component<?> application = new Application();
175 Container system = new Container("all", new Component[] { environment,
176 application }, new ProvidedInterface[0],
177 new RequiredInterface[] { new DefaultRequiredInterface("float",
179 system.getRequiredInterfaces().get(0).setProvider(
180 new DefaultProvidedInterface("hallo", Float.class));
182 List<RequiredInterface> required = system.getRequiredInterfaces();
183 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) {
203 public void testDuplicateComponent() {
205 Component<?> comp1 = new Application();
206 Component<?> comp2 = new Application();
207 Container system = new Container("top");
208 system.addComponent(comp1).addComponent(comp2);
209 } catch (SystemAssemblyException e) {
215 public void testInconsistentHierarchy() {
217 Component<?> comp = new Application();
218 Container system = new Container("top").addComponent(comp);
219 Container system2 = new Container("top2").addComponent(comp);
220 } catch (SystemAssemblyException e) {
226 public void testCompositeWithExternalDependencesProvided() {
228 Component<?> environment = new Environment();
229 Component<?> application = new Application();
230 Container system = new Container("all",
231 new Component[] { application }, new ProvidedInterface[0],
232 application.getRequiredInterfaces().toArray(
233 new RequiredInterface[0]));
234 environment.start(new DefaultScope(new ProvidedInterface[0]));
235 system.getRequiredInterfaces().get(0).setProvider(
236 environment.getProvidedInterfaces().get(0));
237 system.getRequiredInterfaces().get(1).setProvider(
238 environment.getProvidedInterfaces().get(1));
241 List<RequiredInterface> required = system.getRequiredInterfaces();
242 assertEquals(2, required.size());
243 List<ProvidedInterface> provided = system.getProvidedInterfaces();
244 assertEquals(0, provided.size());
248 public void testAmbiguousInterfaces() {
250 Component<?> environment1 = new Environment();
251 Component<?> environment2 = new Environment();
252 Component<?> application = new Application();
253 Container container = new Container("root", new Component[] {
254 environment1, environment2, application },
255 new ProvidedInterface[0], new RequiredInterface[0]);
258 } catch (SystemAssemblyException e) {
264 public void testIncompleteRequirements() {
266 Component<?> application = new Application();
267 Container system = new Container("all",
268 new Component[] { application }, new ProvidedInterface[0],
269 new RequiredInterface[0]);
271 } catch (SystemAssemblyException e) {
277 public void testEnvironmentApplicationRollbackOnException()
279 Environment environment = new Environment(_tracker);
280 Application application = new Application() {
282 public Object doStart(Scope aScope) {
283 throw new RuntimeException();
288 Container container = new Container("root", new Component[] {
289 environment, application }, new ProvidedInterface[0],
290 new RequiredInterface[0]);
293 } catch (RuntimeException e) {
294 AssertionUtils.assertEquals(new String[] { "start.environment",
295 "stop.environment" }, _tracker.getEvents(
296 Thread.currentThread()).toArray(new String[0]));
302 public void testEnvironmentApplicationRollbackOnExceptionWithExceptionOnStop()
305 Environment environment = new Environment(_tracker);
306 // Application 1 will throw an exception while stopping.
307 Application application1 = new Application("app1") {
309 public void doStop(Object aRuntime) {
310 throw new RuntimeException();
314 // application 2 will throw an exception while starting
315 Application application2 = new Application("app2") {
316 public Object doStart(Scope aScope) {
317 throw new RuntimeException();
322 Container container = new Container("root", new Component[] {
323 environment, application1, application2 },
324 new ProvidedInterface[0], new RequiredInterface[0]);
327 } catch (RuntimeException e) {
328 AssertionUtils.assertEquals(new String[] { "start.environment",
329 "stop.environment" }, _tracker.getEvents(
330 Thread.currentThread()).toArray(new String[0]));
336 public void testOptionalRequiredInterfaceProvidedOptionalInternal() {
337 Application application = new Application(true);
338 Container container = new Container("top",
339 new Component[] { application }, new ProvidedInterface[0],
340 Application.required(true));
341 Environment env = new Environment();
342 container.getRequiredInterfaces().get(0).setProvider(
343 env.getProvidedInterfaces().get(0));
344 container.getRequiredInterfaces().get(1).setProvider(
345 env.getProvidedInterfaces().get(1));
346 Scope external = new DefaultScope(env.getProvidedInterfaces());
349 container.start(external);
350 assertSame(env.getProvidedInterfaces().get(0), container
351 .getRequiredInterfaces().get(0).getProvider());
352 assertSame(env.getProvidedInterfaces().get(1), container
353 .getRequiredInterfaces().get(1).getProvider());
354 assertSame(env.getProvidedInterfaces().get(0), application
355 .getRequiredInterfaces().get(0).getProvider());
356 assertSame(env.getProvidedInterfaces().get(1), application
357 .getRequiredInterfaces().get(1).getProvider());
360 public void testOptionalRequiredInterfaceNotProvidedOptionalInternal() {
361 Application application = new Application(true);
362 Container container = new Container("top",
363 new Component[] { application }, new ProvidedInterface[0],
364 Application.required(true));
365 Environment env = new Environment();
366 container.getRequiredInterfaces().get(0).setProvider(
367 env.getProvidedInterfaces().get(0));
368 Scope external = new DefaultScope(new ProvidedInterface[0]);
369 external.publishInterface(env.getProvidedInterfaces().get(0), env
371 container.start(external);
372 assertSame(env.getProvidedInterfaces().get(0), container
373 .getRequiredInterfaces().get(0).getProvider());
374 assertNull(container.getRequiredInterfaces().get(1).getProvider());
375 assertSame(env.getProvidedInterfaces().get(0), application
376 .getRequiredInterfaces().get(0).getProvider());
377 assertNull(application.getRequiredInterfaces().get(1).getProvider());
380 public void testOptionalRequiredInterfaceProvidedMandatoryInternal() {
381 Application application = new Application();
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));
388 container.getRequiredInterfaces().get(1).setProvider(
389 env.getProvidedInterfaces().get(1));
392 } catch (SystemAssemblyException e) {
398 public void testSealed() {
399 final Container container = new Container("xx");
400 assertFalse(container.isSealed());
402 assertTrue(container.isSealed());
404 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
406 public void run() throws Exception {
407 container.addComponent(new Application());
409 }, SystemAssemblyException.class);
411 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
413 public void run() throws Exception {
414 container.connectRequiredProvided("x", "y", "a", "b");
416 }, SystemAssemblyException.class);
417 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
419 public void run() throws Exception {
420 container.connectExternalRequired("x", "y", "a");
422 }, SystemAssemblyException.class);
423 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
425 public void run() throws Exception {
426 container.connectExternalProvided("x", "y", "z");
428 }, SystemAssemblyException.class);
429 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
431 public void run() throws Exception {
432 container.addProvidedInterface(new DefaultProvidedInterface(
433 "xx", String.class));
435 }, SystemAssemblyException.class);
437 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
439 public void run() throws Exception {
440 container.addRequiredInterface(new DefaultRequiredInterface(
441 "xx", String.class));
443 }, SystemAssemblyException.class);
446 public void testRestriction() {
447 Environment env1 = new Environment("env1");
448 Environment env2 = new Environment("env2");
449 Application app = new Application("app");
450 Container container = new Container("top").addComponent(env1)
451 .addComponent(env2).addComponent(app);
452 container.connectRequiredProvided("app", null, "env1", null);
454 assertEquals(env1.getString(), app.getString());
455 assertEquals(env1.getInteger(), app.getInteger());
456 assertFalse(env2.getString().equals(app.getString()));
457 assertFalse(env2.getInteger().equals(app.getInteger()));
460 public void testRestrictionWithFromAndToInterfaceName() {
461 Environment env1 = new Environment("env1");
462 Environment env2 = new Environment("env2");
463 Application app = new Application("app");
464 Container container = new Container("top").addComponent(env1)
465 .addComponent(env2).addComponent(app);
466 container.connectRequiredProvided("app", app.getRequiredInterfaces()
467 .get(0).getName(), "env1", env1.getProvidedInterfaces().get(0)
469 container.connectRequiredProvided("app", app.getRequiredInterfaces()
470 .get(1).getName(), "env2", env2.getProvidedInterfaces().get(1)
473 assertEquals(env1.getString(), app.getString());
474 assertEquals(env2.getInteger(), app.getInteger());
475 assertFalse(env2.getString().equals(app.getString()));
476 assertFalse(env1.getInteger().equals(app.getInteger()));
479 public void testRestrictionWrongComponentNames() {
480 Environment env1 = new Environment("env1");
481 Environment env2 = new Environment("env2");
482 Application app = new Application("app");
483 final Container container = new Container("top").addComponent(env1)
484 .addComponent(env2).addComponent(app);
485 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
487 public void run() throws Exception {
488 container.connectRequiredProvided("app2", null, "env1", null);
490 }, SystemAssemblyException.class);
491 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
493 public void run() throws Exception {
494 container.connectRequiredProvided("app", null, "env3", null);
496 }, SystemAssemblyException.class);
499 public void testRestrictionWrongInterfaceNames() {
500 final Environment env1 = new Environment("env1");
501 Environment env2 = new Environment("env2");
502 final Application app = new Application("app");
503 final Container container = new Container("top").addComponent(env1)
504 .addComponent(env2).addComponent(app);
505 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
507 public void run() throws Exception {
508 container.connectRequiredProvided("app", app
509 .getRequiredInterfaces().get(0).getName()
510 + "xxx", "env1", null);
512 }, SystemAssemblyException.class);
513 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
515 public void run() throws Exception {
516 container.connectRequiredProvided("app", null, "env1", env1
517 .getProvidedInterfaces().get(0).getName()
520 }, SystemAssemblyException.class);
523 public void testProvidedInDifferentScopes() {
524 // Scoping problem occurred. Externally and internally provided
525 // components clashed
526 // because unique id generation in the scope was wrong.
528 StringComponent str = new StringComponent("string");
529 Application app = new Application("app");
530 Container container = new Container("top").addComponent(str)
532 container.addRequiredInterface(new DefaultRequiredInterface("integer",
535 ProvidedInterface provided = new DefaultProvidedInterface("hallo",
537 container.getRequiredInterfaces().get(0).setProvider(provided);
539 Scope external = new DefaultScope(new ProvidedInterface[0]);
540 external.publishInterface(provided, 100);
541 Scope scope = container.start(external);
544 public void testProvidedInterfaces() {
545 Environment env = new Environment(_tracker);
546 Container envcontainer = new Container("0").addComponent(env)
547 .addProvidedInterface(
548 new DefaultProvidedInterface("string", String.class))
549 .addProvidedInterface(
550 new DefaultProvidedInterface("integer", Integer.class));
551 Scope scope = envcontainer.start();
553 AssertionUtils.assertEquals(new String[] { "start.environment" },
554 _tracker.getEvents(Thread.currentThread()).toArray(
557 envcontainer.stop(scope);
560 public void testCoupleTwoContainers() {
561 Environment env = new Environment(_tracker);
562 Container envcontainer = new Container("0").addComponent(env)
563 .addProvidedInterface(
564 new DefaultProvidedInterface("string", String.class))
565 .addProvidedInterface(
566 new DefaultProvidedInterface("integer", Integer.class));
568 Application app = new Application(_tracker);
569 Container appcontainer = new Container("1").addComponent(app)
570 .addRequiredInterface(
571 new DefaultRequiredInterface("string", String.class))
572 .addRequiredInterface(
573 new DefaultRequiredInterface("integer", Integer.class));
575 Container top = new Container("top");
576 top.addComponent(envcontainer).addComponent(appcontainer);
579 AssertionUtils.assertEquals(new String[] { "start.environment",
580 "start.application" }, _tracker.getEvents(
581 Thread.currentThread()).toArray(new String[0]));
585 public void testNonUniqueRequiredInterface() {
586 final Container container = new Container("top");
587 container.addRequiredInterface(new DefaultRequiredInterface("i",
589 container.addRequiredInterface(new DefaultRequiredInterface("x",
591 container.addRequiredInterface(new DefaultRequiredInterface("y",
594 Application app = new Application("1");
595 container.addComponent(app);
597 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
599 public void run() throws Exception {
602 }, SystemAssemblyException.class);
604 container.connectExternalRequired("1", app.getRequiredInterfaces().get(
607 ProvidedInterface i = new DefaultProvidedInterface("i", Integer.class);
608 ProvidedInterface x = new DefaultProvidedInterface("x", String.class);
609 ProvidedInterface y = new DefaultProvidedInterface("y", String.class);
611 Scope externalScope = new DefaultScope(new ProvidedInterface[0]);
613 externalScope.publishInterface(i, 100);
614 externalScope.publishInterface(x, "x-value");
615 externalScope.publishInterface(y, "y-value");
617 container.getRequiredInterfaces().get(0).setProvider(i);
618 container.getRequiredInterfaces().get(1).setProvider(x);
619 container.getRequiredInterfaces().get(2).setProvider(y);
621 Scope runtime = container.start(externalScope);
623 assertEquals("y-value", app.getString());
627 public void testNonUniqueRequiredInterfaceWrongNames() {
628 final Container container = new Container("top");
629 container.addRequiredInterface(new DefaultRequiredInterface("i",
631 container.addRequiredInterface(new DefaultRequiredInterface("x",
633 container.addRequiredInterface(new DefaultRequiredInterface("y",
636 final Application app = new Application("1");
637 container.addComponent(app);
639 // wrong component name.
640 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
642 public void run() throws Exception {
643 container.connectExternalRequired("2", "x", "y");
645 }, SystemAssemblyException.class);
647 // Wrong interface name of component.
648 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
650 public void run() throws Exception {
651 container.connectExternalRequired("1", app
652 .getRequiredInterfaces().get(0).getName()
655 }, SystemAssemblyException.class);
657 // Wrong external interface name of container
658 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
660 public void run() throws Exception {
661 container.connectExternalRequired("1", app
662 .getRequiredInterfaces().get(0).getName(), "z");
664 }, SystemAssemblyException.class);
667 public void testNonUniqueProvidedInterface() {
669 final Container container = new Container("top")
670 .addProvidedInterface(new DefaultProvidedInterface("external",
672 Environment env1 = new Environment("env1");
673 Environment env2 = new Environment("env2");
675 container.addComponent(env1);
676 container.addComponent(env2);
678 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
680 public void run() throws Exception {
683 }, SystemAssemblyException.class);
687 container.connectExternalProvided(container.getProvidedInterfaces()
688 .get(0).getName(), env2.getName(), env2.getProvidedInterfaces()
691 Scope scope = container.start();
693 // check the value of the provided interface of the container
695 String value = scope.getInterfaceImplementation(container
696 .getProvidedInterfaces().get(0), String.class);
697 assertNotNull(value);
698 assertEquals(value, env2.getString());
699 assertFalse(value.equals(env1.getString()));
702 public void testNonUniqueProvidedInterfaceWrongNames() {
704 final Container container = new Container("top")
705 .addProvidedInterface(new DefaultProvidedInterface("external",
707 final Environment env1 = new Environment("env1");
708 final Environment env2 = new Environment("env2");
710 container.addComponent(env1);
711 container.addComponent(env2);
713 // Wrong external provided interface name
714 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
716 public void run() throws Exception {
717 container.connectExternalProvided(container
718 .getProvidedInterfaces().get(0).getName()
719 + "xx", "env1", env1.getProvidedInterfaces().get(0)
722 }, SystemAssemblyException.class);
724 // Wrong provided interface name.
725 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
727 public void run() throws Exception {
728 container.connectExternalProvided(container
729 .getProvidedInterfaces().get(0).getName(), "env1", env1
730 .getProvidedInterfaces().get(0).getName()
733 }, SystemAssemblyException.class);
735 // Wrong provided component
736 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
738 public void run() throws Exception {
739 container.connectExternalProvided(container
740 .getProvidedInterfaces().get(0).getName(), "env3", env1
741 .getProvidedInterfaces().get(0).getName());
743 }, SystemAssemblyException.class);