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 static org.mockito.Matchers.*;
19 import static org.mockito.Mockito.*;
21 import java.io.Serializable;
22 import java.util.ArrayList;
23 import java.util.List;
25 import junit.framework.TestCase;
27 import org.wamblee.general.Pair;
28 import org.wamblee.system.core.Component;
29 import org.wamblee.system.core.DefaultProvidedInterface;
30 import org.wamblee.system.core.DefaultRequiredInterface;
31 import org.wamblee.system.core.DefaultScope;
32 import org.wamblee.system.core.Environment;
33 import org.wamblee.system.core.ProvidedInterface;
34 import org.wamblee.system.core.RequiredInterface;
35 import org.wamblee.system.core.Scope;
36 import org.wamblee.system.core.StringComponent;
37 import org.wamblee.system.core.SystemAssemblyException;
38 import org.wamblee.test.AssertionUtils;
39 import org.wamblee.test.EventTracker;
41 public class ContainerTest extends TestCase {
43 private EventTracker<String> _tracker;
46 protected void setUp() throws Exception {
48 _tracker = new EventTracker<String>();
51 private static class MyMultiple implements Serializable, Runnable {
58 private List<Pair<ProvidedInterface, Component>> createProvidedInput(
59 ProvidedInterface[] aProvided, Component aProvider) {
60 List<Pair<ProvidedInterface, Component>> result = new ArrayList<Pair<ProvidedInterface, Component>>();
61 for (ProvidedInterface provided : aProvided) {
62 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(
78 Thread.currentThread()).toArray(new String[0]));
79 assertEquals(0, scope.getProvidedInterfaces().size());
81 assertEquals(environment.getString(), application.getString());
82 assertEquals(environment.getInteger(), application.getInteger());
86 public void testEnvironmentApplicationSimpleConstructor() {
87 Environment environment = new Environment(_tracker);
88 Application application = new Application(_tracker);
89 Container container = new Container("root").addComponent(environment)
90 .addComponent(application);
92 Scope scope = container.start();
93 AssertionUtils.assertEquals(new String[] { "start.environment",
94 "start.application" }, _tracker.getEvents(
95 Thread.currentThread()).toArray(new String[0]));
96 assertEquals(0, scope.getProvidedInterfaces().size());
98 assertEquals(environment.getString(), application.getString());
99 assertEquals(environment.getInteger(), application.getInteger());
103 public void testApplicationEnvironment() {
105 Component<?> environment = new Environment();
106 Component<?> application = new Application();
107 Container container = new Container("root", new Component[] {
108 application, environment }, new ProvidedInterface[0],
109 new RequiredInterface[0]);
111 } catch (SystemAssemblyException e) {
112 // e.printStackTrace();
118 public void testComposite() {
119 Component<?> environment = new Environment(_tracker);
120 Component<?> application = new Application(_tracker);
121 assertEquals(0, _tracker.getEventCount());
123 Container system = new Container("all", new Component[] { environment,
124 application }, new ProvidedInterface[0],
125 new RequiredInterface[0]);
126 Scope runtime = system.start();
127 List<RequiredInterface> required = system.getRequiredInterfaces();
128 assertEquals(0, required.size());
129 List<ProvidedInterface> provided = system.getProvidedInterfaces();
130 assertEquals(0, provided.size());
132 AssertionUtils.assertEquals(new String[] { "start.environment",
133 "start.application" }, _tracker.getEvents(
134 Thread.currentThread()).toArray(new String[0]));
137 system.stop(runtime);
138 AssertionUtils.assertEquals(new String[] { "stop.application",
139 "stop.environment" }, _tracker
140 .getEvents(Thread.currentThread()).toArray(new String[0]));
144 public void testCompositeWithWrongProvidedInfo() {
146 Component<?> environment = new Environment();
147 Component<?> application = new Application();
148 Container system = new Container("all", new Component[] {
149 environment, application },
150 new ProvidedInterface[] { new DefaultProvidedInterface(
151 "float", Float.class) },
152 new DefaultRequiredInterface[0]);
154 } catch (SystemAssemblyException e) {
160 public void testCompositeRequiredInterfaceNotProvided() {
162 Component<?> environment = new Environment();
163 Component<?> application = new Application();
164 Container system = new Container("all", new Component[] {
165 environment, application }, new ProvidedInterface[0],
166 new RequiredInterface[] { new DefaultRequiredInterface(
167 "string", String.class) });
169 } catch (SystemAssemblyException e) {
175 public void testCompositeWithSuperfluousRequiredInfo() {
176 Component<?> environment = new Environment();
177 Component<?> application = new Application();
178 Container system = new Container("all", new Component[] { environment,
179 application }, new ProvidedInterface[0],
180 new RequiredInterface[] { new DefaultRequiredInterface("float",
182 system.getRequiredInterfaces().get(0).setProvider(
183 new DefaultProvidedInterface("hallo", Float.class));
185 List<RequiredInterface> required = system.getRequiredInterfaces();
186 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) {
206 public void testDuplicateComponent() {
208 Component<?> comp1 = new Application();
209 Component<?> comp2 = new Application();
210 Container system = new Container("top");
211 system.addComponent(comp1).addComponent(comp2);
212 } catch (SystemAssemblyException e) {
218 public void testInconsistentHierarchy() {
220 Component<?> comp = new Application();
221 Container system = new Container("top").addComponent(comp);
222 Container system2 = new Container("top2").addComponent(comp);
223 } catch (SystemAssemblyException e) {
229 public void testCompositeWithExternalDependencesProvided() {
231 Component<?> environment = new Environment();
232 Component<?> application = new Application();
233 Container system = new Container("all",
234 new Component[] { application }, new ProvidedInterface[0],
235 application.getRequiredInterfaces().toArray(
236 new RequiredInterface[0]));
237 environment.start(new DefaultScope(new ProvidedInterface[0]));
238 system.getRequiredInterfaces().get(0).setProvider(
239 environment.getProvidedInterfaces().get(0));
240 system.getRequiredInterfaces().get(1).setProvider(
241 environment.getProvidedInterfaces().get(1));
244 List<RequiredInterface> required = system.getRequiredInterfaces();
245 assertEquals(2, required.size());
246 List<ProvidedInterface> provided = system.getProvidedInterfaces();
247 assertEquals(0, provided.size());
251 public void testAmbiguousInterfaces() {
253 Component<?> environment1 = new Environment();
254 Component<?> environment2 = new Environment();
255 Component<?> application = new Application();
256 Container container = new Container("root", new Component[] {
257 environment1, environment2, application },
258 new ProvidedInterface[0], new RequiredInterface[0]);
261 } catch (SystemAssemblyException e) {
267 public void testIncompleteRequirements() {
269 Component<?> application = new Application();
270 Container system = new Container("all",
271 new Component[] { application }, new ProvidedInterface[0],
272 new RequiredInterface[0]);
274 } catch (SystemAssemblyException e) {
280 public void testEnvironmentApplicationRollbackOnException()
282 Environment environment = new Environment(_tracker);
283 Application application = new Application() {
285 public Object doStart(Scope aScope) {
286 throw new RuntimeException();
291 Container container = new Container("root", new Component[] {
292 environment, application }, new ProvidedInterface[0],
293 new RequiredInterface[0]);
296 } catch (RuntimeException e) {
297 AssertionUtils.assertEquals(new String[] { "start.environment",
298 "stop.environment" }, _tracker.getEvents(
299 Thread.currentThread()).toArray(new String[0]));
305 public void testEnvironmentApplicationRollbackOnExceptionWithExceptionOnStop()
308 Environment environment = new Environment(_tracker);
309 // Application 1 will throw an exception while stopping.
310 Application application1 = new Application("app1") {
312 public void doStop(Object aRuntime) {
313 throw new RuntimeException();
317 // application 2 will throw an exception while starting
318 Application application2 = new Application("app2") {
319 public Object doStart(Scope aScope) {
320 throw new RuntimeException();
325 Container container = new Container("root", new Component[] {
326 environment, application1, application2 },
327 new ProvidedInterface[0], new RequiredInterface[0]);
330 } catch (RuntimeException e) {
331 AssertionUtils.assertEquals(new String[] { "start.environment",
332 "stop.environment" }, _tracker.getEvents(
333 Thread.currentThread()).toArray(new String[0]));
339 public void testOptionalRequiredInterfaceProvidedOptionalInternal() {
340 Application application = new Application(true);
341 Container container = new Container("top",
342 new Component[] { application }, new ProvidedInterface[0],
343 Application.required(true));
344 Environment env = new Environment();
345 container.getRequiredInterfaces().get(0).setProvider(
346 env.getProvidedInterfaces().get(0));
347 container.getRequiredInterfaces().get(1).setProvider(
348 env.getProvidedInterfaces().get(1));
349 Scope external = new DefaultScope(env.getProvidedInterfaces());
352 container.start(external);
353 assertSame(env.getProvidedInterfaces().get(0), container
354 .getRequiredInterfaces().get(0).getProvider());
355 assertSame(env.getProvidedInterfaces().get(1), container
356 .getRequiredInterfaces().get(1).getProvider());
357 assertSame(env.getProvidedInterfaces().get(0), application
358 .getRequiredInterfaces().get(0).getProvider());
359 assertSame(env.getProvidedInterfaces().get(1), application
360 .getRequiredInterfaces().get(1).getProvider());
363 public void testOptionalRequiredInterfaceNotProvidedOptionalInternal() {
364 Application application = new Application(true);
365 Container container = new Container("top",
366 new Component[] { application }, new ProvidedInterface[0],
367 Application.required(true));
368 Environment env = new Environment();
369 container.getRequiredInterfaces().get(0).setProvider(
370 env.getProvidedInterfaces().get(0));
371 Scope external = new DefaultScope(new ProvidedInterface[0]);
372 external.publishInterface(env.getProvidedInterfaces().get(0), env
374 container.start(external);
375 assertSame(env.getProvidedInterfaces().get(0), container
376 .getRequiredInterfaces().get(0).getProvider());
377 assertNull(container.getRequiredInterfaces().get(1).getProvider());
378 assertSame(env.getProvidedInterfaces().get(0), application
379 .getRequiredInterfaces().get(0).getProvider());
380 assertNull(application.getRequiredInterfaces().get(1).getProvider());
383 public void testOptionalRequiredInterfaceProvidedMandatoryInternal() {
384 Application application = new Application();
385 Container container = new Container("top",
386 new Component[] { application }, new ProvidedInterface[0],
387 Application.required(true));
388 Environment env = new Environment();
389 container.getRequiredInterfaces().get(0).setProvider(
390 env.getProvidedInterfaces().get(0));
391 container.getRequiredInterfaces().get(1).setProvider(
392 env.getProvidedInterfaces().get(1));
395 } catch (SystemAssemblyException e) {
401 public void testSealed() {
402 final Container container = new Container("xx");
403 assertFalse(container.isSealed());
405 assertTrue(container.isSealed());
407 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
409 public void run() throws Exception {
410 container.addComponent(new Application());
412 }, SystemAssemblyException.class);
414 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
416 public void run() throws Exception {
417 container.connectRequiredProvided("x", "y", "a", "b");
419 }, SystemAssemblyException.class);
420 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
422 public void run() throws Exception {
423 container.connectExternalRequired("x", "y", "a");
425 }, SystemAssemblyException.class);
426 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
428 public void run() throws Exception {
429 container.connectExternalProvided("x", "y", "z");
431 }, SystemAssemblyException.class);
432 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
434 public void run() throws Exception {
435 container.addProvidedInterface(new DefaultProvidedInterface(
436 "xx", String.class));
438 }, SystemAssemblyException.class);
440 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
442 public void run() throws Exception {
443 container.addRequiredInterface(new DefaultRequiredInterface(
444 "xx", String.class));
446 }, SystemAssemblyException.class);
449 public void testRestriction() {
450 Environment env1 = new Environment("env1");
451 Environment env2 = new Environment("env2");
452 Application app = new Application("app");
453 Container container = new Container("top").addComponent(env1)
454 .addComponent(env2).addComponent(app);
455 container.connectRequiredProvided("app", null, "env1", null);
457 assertEquals(env1.getString(), app.getString());
458 assertEquals(env1.getInteger(), app.getInteger());
459 assertFalse(env2.getString().equals(app.getString()));
460 assertFalse(env2.getInteger().equals(app.getInteger()));
463 public void testRestrictionWithFromAndToInterfaceName() {
464 Environment env1 = new Environment("env1");
465 Environment env2 = new Environment("env2");
466 Application app = new Application("app");
467 Container container = new Container("top").addComponent(env1)
468 .addComponent(env2).addComponent(app);
469 container.connectRequiredProvided("app", app.getRequiredInterfaces()
470 .get(0).getName(), "env1", env1.getProvidedInterfaces().get(0)
472 container.connectRequiredProvided("app", app.getRequiredInterfaces()
473 .get(1).getName(), "env2", env2.getProvidedInterfaces().get(1)
476 assertEquals(env1.getString(), app.getString());
477 assertEquals(env2.getInteger(), app.getInteger());
478 assertFalse(env2.getString().equals(app.getString()));
479 assertFalse(env1.getInteger().equals(app.getInteger()));
482 public void testRestrictionWrongComponentNames() {
483 Environment env1 = new Environment("env1");
484 Environment env2 = new Environment("env2");
485 Application app = new Application("app");
486 final Container container = new Container("top").addComponent(env1)
487 .addComponent(env2).addComponent(app);
488 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
490 public void run() throws Exception {
491 container.connectRequiredProvided("app2", null, "env1", null);
493 }, SystemAssemblyException.class);
494 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
496 public void run() throws Exception {
497 container.connectRequiredProvided("app", null, "env3", null);
499 }, SystemAssemblyException.class);
502 public void testRestrictionWrongInterfaceNames() {
503 final Environment env1 = new Environment("env1");
504 Environment env2 = new Environment("env2");
505 final 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("app", app
512 .getRequiredInterfaces().get(0).getName()
513 + "xxx", "env1", null);
515 }, SystemAssemblyException.class);
516 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
518 public void run() throws Exception {
519 container.connectRequiredProvided("app", null, "env1", env1
520 .getProvidedInterfaces().get(0).getName()
523 }, SystemAssemblyException.class);
526 public void testProvidedInDifferentScopes() {
527 // Scoping problem occurred. Externally and internally provided
528 // components clashed
529 // because unique id generation in the scope was wrong.
531 StringComponent str = new StringComponent("string");
532 Application app = new Application("app");
533 Container container = new Container("top").addComponent(str)
535 container.addRequiredInterface(new DefaultRequiredInterface("integer",
538 ProvidedInterface provided = new DefaultProvidedInterface("hallo",
540 container.getRequiredInterfaces().get(0).setProvider(provided);
542 Scope external = new DefaultScope(new ProvidedInterface[0]);
543 external.publishInterface(provided, 100);
544 Scope scope = container.start(external);
547 public void testProvidedInterfaces() {
548 Environment env = new Environment(_tracker);
549 Container envcontainer = new Container("0").addComponent(env)
550 .addProvidedInterface(
551 new DefaultProvidedInterface("string", String.class))
552 .addProvidedInterface(
553 new DefaultProvidedInterface("integer", Integer.class));
554 Scope scope = envcontainer.start();
556 AssertionUtils.assertEquals(new String[] { "start.environment" },
557 _tracker.getEvents(Thread.currentThread()).toArray(
560 envcontainer.stop(scope);
563 public void testCoupleTwoContainers() {
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));
571 Application app = new Application(_tracker);
572 Container appcontainer = new Container("1").addComponent(app)
573 .addRequiredInterface(
574 new DefaultRequiredInterface("string", String.class))
575 .addRequiredInterface(
576 new DefaultRequiredInterface("integer", Integer.class));
578 Container top = new Container("top");
579 top.addComponent(envcontainer).addComponent(appcontainer);
582 AssertionUtils.assertEquals(new String[] { "start.environment",
583 "start.application" }, _tracker.getEvents(
584 Thread.currentThread()).toArray(new String[0]));
588 public void testNonUniqueRequiredInterface() {
589 final Container container = new Container("top");
590 container.addRequiredInterface(new DefaultRequiredInterface("i",
592 container.addRequiredInterface(new DefaultRequiredInterface("x",
594 container.addRequiredInterface(new DefaultRequiredInterface("y",
597 Application app = new Application("1");
598 container.addComponent(app);
600 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
602 public void run() throws Exception {
605 }, SystemAssemblyException.class);
607 container.connectExternalRequired("1", app.getRequiredInterfaces().get(
610 ProvidedInterface i = new DefaultProvidedInterface("i", Integer.class);
611 ProvidedInterface x = new DefaultProvidedInterface("x", String.class);
612 ProvidedInterface y = new DefaultProvidedInterface("y", String.class);
614 Scope externalScope = new DefaultScope(new ProvidedInterface[0]);
616 externalScope.publishInterface(i, 100);
617 externalScope.publishInterface(x, "x-value");
618 externalScope.publishInterface(y, "y-value");
620 container.getRequiredInterfaces().get(0).setProvider(i);
621 container.getRequiredInterfaces().get(1).setProvider(x);
622 container.getRequiredInterfaces().get(2).setProvider(y);
624 Scope runtime = container.start(externalScope);
626 assertEquals("y-value", app.getString());
630 public void testNonUniqueRequiredInterfaceWrongNames() {
631 final Container container = new Container("top");
632 container.addRequiredInterface(new DefaultRequiredInterface("i",
634 container.addRequiredInterface(new DefaultRequiredInterface("x",
636 container.addRequiredInterface(new DefaultRequiredInterface("y",
639 final Application app = new Application("1");
640 container.addComponent(app);
642 // wrong component name.
643 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
645 public void run() throws Exception {
646 container.connectExternalRequired("2", "x", "y");
648 }, SystemAssemblyException.class);
650 // Wrong interface name of component.
651 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
653 public void run() throws Exception {
654 container.connectExternalRequired("1", app
655 .getRequiredInterfaces().get(0).getName()
658 }, SystemAssemblyException.class);
660 // Wrong external interface name of container
661 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
663 public void run() throws Exception {
664 container.connectExternalRequired("1", app
665 .getRequiredInterfaces().get(0).getName(), "z");
667 }, SystemAssemblyException.class);
670 public void testNonUniqueProvidedInterface() {
672 final Container container = new Container("top")
673 .addProvidedInterface(new DefaultProvidedInterface("external",
675 Environment env1 = new Environment("env1");
676 Environment env2 = new Environment("env2");
678 container.addComponent(env1);
679 container.addComponent(env2);
681 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
683 public void run() throws Exception {
686 }, SystemAssemblyException.class);
690 container.connectExternalProvided(container.getProvidedInterfaces()
691 .get(0).getName(), env2.getName(), env2.getProvidedInterfaces()
694 Scope scope = container.start();
696 // check the value of the provided interface of the container
698 String value = scope.getInterfaceImplementation(container
699 .getProvidedInterfaces().get(0), String.class);
700 assertNotNull(value);
701 assertEquals(value, env2.getString());
702 assertFalse(value.equals(env1.getString()));
705 public void testNonUniqueProvidedInterfaceWrongNames() {
707 final Container container = new Container("top")
708 .addProvidedInterface(new DefaultProvidedInterface("external",
710 final Environment env1 = new Environment("env1");
711 final Environment env2 = new Environment("env2");
713 container.addComponent(env1);
714 container.addComponent(env2);
716 // Wrong external provided interface name
717 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
719 public void run() throws Exception {
720 container.connectExternalProvided(container
721 .getProvidedInterfaces().get(0).getName()
722 + "xx", "env1", env1.getProvidedInterfaces().get(0)
725 }, SystemAssemblyException.class);
727 // Wrong provided interface name.
728 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
730 public void run() throws Exception {
731 container.connectExternalProvided(container
732 .getProvidedInterfaces().get(0).getName(), "env1", env1
733 .getProvidedInterfaces().get(0).getName()
736 }, SystemAssemblyException.class);
738 // Wrong provided component
739 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
741 public void run() throws Exception {
742 container.connectExternalProvided(container
743 .getProvidedInterfaces().get(0).getName(), "env3", env1
744 .getProvidedInterfaces().get(0).getName());
746 }, SystemAssemblyException.class);