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.easymock.classextension.ConstructorArgs;
25 import org.easymock.classextension.EasyMock;
26 import org.easymock.classextension.IMocksControl;
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.EasyMockMatchers;
40 import org.wamblee.test.EventTracker;
42 public class ContainerTest extends TestCase {
44 private EventTracker<String> _tracker;
47 protected void setUp() throws Exception {
49 _tracker = new EventTracker<String>();
52 private static class MyMultiple implements Serializable, Runnable {
59 private List<Pair<ProvidedInterface, Component>> createProvidedInput(
60 ProvidedInterface[] aProvided, Component aProvider) {
61 List<Pair<ProvidedInterface, Component>> result = new ArrayList<Pair<ProvidedInterface, Component>>();
62 for (ProvidedInterface provided : aProvided) {
63 result.add(new Pair<ProvidedInterface, Component>(provided,
69 public void testEnvironmentApplication() {
70 Environment environment = new Environment(_tracker);
71 Application application = new Application(_tracker);
72 Container container = new Container("root", new Component[] {
73 environment, application }, new ProvidedInterface[0],
74 new RequiredInterface[0]);
75 Scope scope = container.start();
76 assertTrue(container.isSealed());
77 AssertionUtils.assertEquals(new String[] { "start.environment",
78 "start.application" }, _tracker.getEvents(
79 Thread.currentThread()).toArray(new String[0]));
80 assertEquals(0, scope.getProvidedInterfaces().size());
82 assertEquals(environment.getString(), application.getString());
83 assertEquals(environment.getInteger(), application.getInteger());
87 public void testEnvironmentApplicationSimpleConstructor() {
88 Environment environment = new Environment(_tracker);
89 Application application = new Application(_tracker);
90 Container container = new Container("root").addComponent(environment)
91 .addComponent(application);
93 Scope scope = container.start();
94 AssertionUtils.assertEquals(new String[] { "start.environment",
95 "start.application" }, _tracker.getEvents(
96 Thread.currentThread()).toArray(new String[0]));
97 assertEquals(0, scope.getProvidedInterfaces().size());
99 assertEquals(environment.getString(), application.getString());
100 assertEquals(environment.getInteger(), application.getInteger());
104 public void testApplicationEnvironment() {
106 Component<?> environment = new Environment();
107 Component<?> application = new Application();
108 Container container = new Container("root", new Component[] {
109 application, environment }, new ProvidedInterface[0],
110 new RequiredInterface[0]);
112 } catch (SystemAssemblyException e) {
113 // e.printStackTrace();
119 public void testComposite() {
120 Component<?> environment = new Environment(_tracker);
121 Component<?> application = new Application(_tracker);
122 assertEquals(0, _tracker.getEventCount());
124 Container system = new Container("all", new Component[] { environment,
125 application }, new ProvidedInterface[0],
126 new RequiredInterface[0]);
127 Scope runtime = system.start();
128 List<RequiredInterface> required = system.getRequiredInterfaces();
129 assertEquals(0, required.size());
130 List<ProvidedInterface> provided = system.getProvidedInterfaces();
131 assertEquals(0, provided.size());
133 AssertionUtils.assertEquals(new String[] { "start.environment",
134 "start.application" }, _tracker.getEvents(
135 Thread.currentThread()).toArray(new String[0]));
138 system.stop(runtime);
139 AssertionUtils.assertEquals(new String[] { "stop.application",
140 "stop.environment" }, _tracker
141 .getEvents(Thread.currentThread()).toArray(new String[0]));
145 public void testCompositeWithWrongProvidedInfo() {
147 Component<?> environment = new Environment();
148 Component<?> application = new Application();
149 Container system = new Container("all", new Component[] {
150 environment, application },
151 new ProvidedInterface[] { new DefaultProvidedInterface(
152 "float", Float.class) },
153 new DefaultRequiredInterface[0]);
155 } catch (SystemAssemblyException e) {
161 public void testCompositeRequiredInterfaceNotProvided() {
163 Component<?> environment = new Environment();
164 Component<?> application = new Application();
165 Container system = new Container("all", new Component[] {
166 environment, application }, new ProvidedInterface[0],
167 new RequiredInterface[] { new DefaultRequiredInterface(
168 "string", String.class) });
170 } catch (SystemAssemblyException e) {
176 public void testCompositeWithSuperfluousRequiredInfo() {
177 Component<?> environment = new Environment();
178 Component<?> application = new Application();
179 Container system = new Container("all", new Component[] { environment,
180 application }, new ProvidedInterface[0],
181 new RequiredInterface[] { new DefaultRequiredInterface("float",
183 system.getRequiredInterfaces().get(0).setProvider(
184 new DefaultProvidedInterface("hallo", Float.class));
186 List<RequiredInterface> required = system.getRequiredInterfaces();
187 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) {
207 public void testDuplicateComponent() {
209 Component<?> comp1 = new Application();
210 Component<?> comp2 = new Application();
211 Container system = new Container("top");
212 system.addComponent(comp1).addComponent(comp2);
213 } catch (SystemAssemblyException e) {
219 public void testInconsistentHierarchy() {
221 Component<?> comp = new Application();
222 Container system = new Container("top").addComponent(comp);
223 Container system2 = new Container("top2").addComponent(comp);
224 } catch (SystemAssemblyException e) {
230 public void testCompositeWithExternalDependencesProvided() {
232 Component<?> environment = new Environment();
233 Component<?> application = new Application();
234 Container system = new Container("all",
235 new Component[] { application }, new ProvidedInterface[0],
236 application.getRequiredInterfaces().toArray(
237 new RequiredInterface[0]));
238 environment.start(new DefaultScope(new ProvidedInterface[0]));
239 system.getRequiredInterfaces().get(0).setProvider(
240 environment.getProvidedInterfaces().get(0));
241 system.getRequiredInterfaces().get(1).setProvider(
242 environment.getProvidedInterfaces().get(1));
245 List<RequiredInterface> required = system.getRequiredInterfaces();
246 assertEquals(2, required.size());
247 List<ProvidedInterface> provided = system.getProvidedInterfaces();
248 assertEquals(0, provided.size());
252 public void testAmbiguousInterfaces() {
254 Component<?> environment1 = new Environment();
255 Component<?> environment2 = new Environment();
256 Component<?> application = new Application();
257 Container container = new Container("root", new Component[] {
258 environment1, environment2, application },
259 new ProvidedInterface[0], new RequiredInterface[0]);
262 } catch (SystemAssemblyException e) {
268 public void testIncompleteRequirements() {
270 Component<?> application = new Application();
271 Container system = new Container("all",
272 new Component[] { application }, new ProvidedInterface[0],
273 new RequiredInterface[0]);
275 } catch (SystemAssemblyException e) {
281 public void testEnvironmentApplicationRollbackOnException()
283 IMocksControl control = EasyMock.createStrictControl();
285 Environment environment = new Environment(_tracker);
286 Application application = control.createMock(Application.class,
287 new ConstructorArgs(Application.class.getConstructor()),
288 Application.class.getDeclaredMethod("doStart", Scope.class));
290 application.doStart(EasyMockMatchers.anyObject(Scope.class));
291 EasyMock.expectLastCall().andThrow(new RuntimeException());
295 Container container = new Container("root", new Component[] {
296 environment, application }, new ProvidedInterface[0],
297 new RequiredInterface[0]);
300 } catch (RuntimeException e) {
301 AssertionUtils.assertEquals(new String[] { "start.environment",
302 "stop.environment" }, _tracker.getEvents(
303 Thread.currentThread()).toArray(new String[0]));
309 public void testEnvironmentApplicationRollbackOnExceptionWithExceptionOnStop()
311 IMocksControl control = EasyMock.createControl();
313 Environment environment = new Environment(_tracker);
314 // Application 1 will throw an exception while stopping.
315 Application application1 = control.createMock(Application.class,
316 new ConstructorArgs(Application.class.getConstructor()),
317 Application.class.getDeclaredMethod("doStop", Object.class));
319 application1.doStop(EasyMock.anyObject());
320 EasyMock.expectLastCall().andThrow(new RuntimeException());
322 // application 2 will throw an exception while starting
323 Application application2 = control.createMock(Application.class,
324 new ConstructorArgs(Application.class
325 .getConstructor(String.class), "application2"),
326 Application.class.getDeclaredMethod("doStart", Scope.class));
328 application2.doStart(EasyMockMatchers.anyObject(Scope.class));
329 EasyMock.expectLastCall().andThrow(new RuntimeException());
334 Container container = new Container("root", new Component[] {
335 environment, application1, application2 },
336 new ProvidedInterface[0], new RequiredInterface[0]);
339 } catch (RuntimeException e) {
340 AssertionUtils.assertEquals(new String[] { "start.environment",
341 "stop.environment" }, _tracker.getEvents(
342 Thread.currentThread()).toArray(new String[0]));
348 public void testOptionalRequiredInterfaceProvidedOptionalInternal() {
349 Application application = new Application(true);
350 Container container = new Container("top",
351 new Component[] { application }, new ProvidedInterface[0],
352 Application.required(true));
353 Environment env = new Environment();
354 container.getRequiredInterfaces().get(0).setProvider(
355 env.getProvidedInterfaces().get(0));
356 container.getRequiredInterfaces().get(1).setProvider(
357 env.getProvidedInterfaces().get(1));
358 Scope external = new DefaultScope(env.getProvidedInterfaces());
361 container.start(external);
362 assertSame(env.getProvidedInterfaces().get(0), container
363 .getRequiredInterfaces().get(0).getProvider());
364 assertSame(env.getProvidedInterfaces().get(1), container
365 .getRequiredInterfaces().get(1).getProvider());
366 assertSame(env.getProvidedInterfaces().get(0), application
367 .getRequiredInterfaces().get(0).getProvider());
368 assertSame(env.getProvidedInterfaces().get(1), application
369 .getRequiredInterfaces().get(1).getProvider());
372 public void testOptionalRequiredInterfaceNotProvidedOptionalInternal() {
373 Application application = new Application(true);
374 Container container = new Container("top",
375 new Component[] { application }, new ProvidedInterface[0],
376 Application.required(true));
377 Environment env = new Environment();
378 container.getRequiredInterfaces().get(0).setProvider(
379 env.getProvidedInterfaces().get(0));
380 Scope external = new DefaultScope(new ProvidedInterface[0]);
381 external.publishInterface(env.getProvidedInterfaces().get(0), env
383 container.start(external);
384 assertSame(env.getProvidedInterfaces().get(0), container
385 .getRequiredInterfaces().get(0).getProvider());
386 assertNull(container.getRequiredInterfaces().get(1).getProvider());
387 assertSame(env.getProvidedInterfaces().get(0), application
388 .getRequiredInterfaces().get(0).getProvider());
389 assertNull(application.getRequiredInterfaces().get(1).getProvider());
392 public void testOptionalRequiredInterfaceProvidedMandatoryInternal() {
393 Application application = new Application();
394 Container container = new Container("top",
395 new Component[] { application }, new ProvidedInterface[0],
396 Application.required(true));
397 Environment env = new Environment();
398 container.getRequiredInterfaces().get(0).setProvider(
399 env.getProvidedInterfaces().get(0));
400 container.getRequiredInterfaces().get(1).setProvider(
401 env.getProvidedInterfaces().get(1));
404 } catch (SystemAssemblyException e) {
410 public void testSealed() {
411 final Container container = new Container("xx");
412 assertFalse(container.isSealed());
414 assertTrue(container.isSealed());
416 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
418 public void run() throws Exception {
419 container.addComponent(new Application());
421 }, SystemAssemblyException.class);
423 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
425 public void run() throws Exception {
426 container.connectRequiredProvided("x", "y", "a", "b");
428 }, SystemAssemblyException.class);
429 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
431 public void run() throws Exception {
432 container.connectExternalRequired("x", "y", "a");
434 }, SystemAssemblyException.class);
435 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
437 public void run() throws Exception {
438 container.connectExternalProvided("x", "y", "z");
440 }, SystemAssemblyException.class);
441 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
443 public void run() throws Exception {
444 container.addProvidedInterface(new DefaultProvidedInterface(
445 "xx", String.class));
447 }, SystemAssemblyException.class);
449 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
451 public void run() throws Exception {
452 container.addRequiredInterface(new DefaultRequiredInterface(
453 "xx", String.class));
455 }, SystemAssemblyException.class);
458 public void testRestriction() {
459 Environment env1 = new Environment("env1");
460 Environment env2 = new Environment("env2");
461 Application app = new Application("app");
462 Container container = new Container("top").addComponent(env1)
463 .addComponent(env2).addComponent(app);
464 container.connectRequiredProvided("app", null, "env1", null);
466 assertEquals(env1.getString(), app.getString());
467 assertEquals(env1.getInteger(), app.getInteger());
468 assertFalse(env2.getString().equals(app.getString()));
469 assertFalse(env2.getInteger().equals(app.getInteger()));
472 public void testRestrictionWithFromAndToInterfaceName() {
473 Environment env1 = new Environment("env1");
474 Environment env2 = new Environment("env2");
475 Application app = new Application("app");
476 Container container = new Container("top").addComponent(env1)
477 .addComponent(env2).addComponent(app);
478 container.connectRequiredProvided("app", app.getRequiredInterfaces()
479 .get(0).getName(), "env1", env1.getProvidedInterfaces().get(0)
481 container.connectRequiredProvided("app", app.getRequiredInterfaces()
482 .get(1).getName(), "env2", env2.getProvidedInterfaces().get(1)
485 assertEquals(env1.getString(), app.getString());
486 assertEquals(env2.getInteger(), app.getInteger());
487 assertFalse(env2.getString().equals(app.getString()));
488 assertFalse(env1.getInteger().equals(app.getInteger()));
491 public void testRestrictionWrongComponentNames() {
492 Environment env1 = new Environment("env1");
493 Environment env2 = new Environment("env2");
494 Application app = new Application("app");
495 final Container container = new Container("top").addComponent(env1)
496 .addComponent(env2).addComponent(app);
497 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
499 public void run() throws Exception {
500 container.connectRequiredProvided("app2", null, "env1", null);
502 }, SystemAssemblyException.class);
503 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
505 public void run() throws Exception {
506 container.connectRequiredProvided("app", null, "env3", null);
508 }, SystemAssemblyException.class);
511 public void testRestrictionWrongInterfaceNames() {
512 final Environment env1 = new Environment("env1");
513 Environment env2 = new Environment("env2");
514 final Application app = new Application("app");
515 final Container container = new Container("top").addComponent(env1)
516 .addComponent(env2).addComponent(app);
517 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
519 public void run() throws Exception {
520 container.connectRequiredProvided("app", app
521 .getRequiredInterfaces().get(0).getName()
522 + "xxx", "env1", null);
524 }, SystemAssemblyException.class);
525 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
527 public void run() throws Exception {
528 container.connectRequiredProvided("app", null, "env1", env1
529 .getProvidedInterfaces().get(0).getName()
532 }, SystemAssemblyException.class);
535 public void testProvidedInDifferentScopes() {
536 // Scoping problem occurred. Externally and internally provided
537 // components clashed
538 // because unique id generation in the scope was wrong.
540 StringComponent str = new StringComponent("string");
541 Application app = new Application("app");
542 Container container = new Container("top").addComponent(str)
544 container.addRequiredInterface(new DefaultRequiredInterface("integer",
547 ProvidedInterface provided = new DefaultProvidedInterface("hallo",
549 container.getRequiredInterfaces().get(0).setProvider(provided);
551 Scope external = new DefaultScope(new ProvidedInterface[0]);
552 external.publishInterface(provided, 100);
553 Scope scope = container.start(external);
556 public void testProvidedInterfaces() {
557 Environment env = new Environment(_tracker);
558 Container envcontainer = new Container("0").addComponent(env)
559 .addProvidedInterface(
560 new DefaultProvidedInterface("string", String.class))
561 .addProvidedInterface(
562 new DefaultProvidedInterface("integer", Integer.class));
563 Scope scope = envcontainer.start();
565 AssertionUtils.assertEquals(new String[] { "start.environment" },
566 _tracker.getEvents(Thread.currentThread()).toArray(
569 envcontainer.stop(scope);
572 public void testCoupleTwoContainers() {
573 Environment env = new Environment(_tracker);
574 Container envcontainer = new Container("0").addComponent(env)
575 .addProvidedInterface(
576 new DefaultProvidedInterface("string", String.class))
577 .addProvidedInterface(
578 new DefaultProvidedInterface("integer", Integer.class));
580 Application app = new Application(_tracker);
581 Container appcontainer = new Container("1").addComponent(app)
582 .addRequiredInterface(
583 new DefaultRequiredInterface("string", String.class))
584 .addRequiredInterface(
585 new DefaultRequiredInterface("integer", Integer.class));
587 Container top = new Container("top");
588 top.addComponent(envcontainer).addComponent(appcontainer);
591 AssertionUtils.assertEquals(new String[] { "start.environment",
592 "start.application" }, _tracker.getEvents(
593 Thread.currentThread()).toArray(new String[0]));
597 public void testNonUniqueRequiredInterface() {
598 final Container container = new Container("top");
599 container.addRequiredInterface(new DefaultRequiredInterface("i",
601 container.addRequiredInterface(new DefaultRequiredInterface("x",
603 container.addRequiredInterface(new DefaultRequiredInterface("y",
606 Application app = new Application("1");
607 container.addComponent(app);
609 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
611 public void run() throws Exception {
614 }, SystemAssemblyException.class);
616 container.connectExternalRequired("1", app.getRequiredInterfaces().get(
619 ProvidedInterface i = new DefaultProvidedInterface("i", Integer.class);
620 ProvidedInterface x = new DefaultProvidedInterface("x", String.class);
621 ProvidedInterface y = new DefaultProvidedInterface("y", String.class);
623 Scope externalScope = new DefaultScope(new ProvidedInterface[0]);
625 externalScope.publishInterface(i, 100);
626 externalScope.publishInterface(x, "x-value");
627 externalScope.publishInterface(y, "y-value");
629 container.getRequiredInterfaces().get(0).setProvider(i);
630 container.getRequiredInterfaces().get(1).setProvider(x);
631 container.getRequiredInterfaces().get(2).setProvider(y);
633 Scope runtime = container.start(externalScope);
635 assertEquals("y-value", app.getString());
639 public void testNonUniqueRequiredInterfaceWrongNames() {
640 final Container container = new Container("top");
641 container.addRequiredInterface(new DefaultRequiredInterface("i",
643 container.addRequiredInterface(new DefaultRequiredInterface("x",
645 container.addRequiredInterface(new DefaultRequiredInterface("y",
648 final Application app = new Application("1");
649 container.addComponent(app);
651 // wrong component name.
652 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
654 public void run() throws Exception {
655 container.connectExternalRequired("2", "x", "y");
657 }, SystemAssemblyException.class);
659 // Wrong interface name of component.
660 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
662 public void run() throws Exception {
663 container.connectExternalRequired("1", app
664 .getRequiredInterfaces().get(0).getName()
667 }, SystemAssemblyException.class);
669 // Wrong external interface name of container
670 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
672 public void run() throws Exception {
673 container.connectExternalRequired("1", app
674 .getRequiredInterfaces().get(0).getName(), "z");
676 }, SystemAssemblyException.class);
679 public void testNonUniqueProvidedInterface() {
681 final Container container = new Container("top")
682 .addProvidedInterface(new DefaultProvidedInterface("external",
684 Environment env1 = new Environment("env1");
685 Environment env2 = new Environment("env2");
687 container.addComponent(env1);
688 container.addComponent(env2);
690 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
692 public void run() throws Exception {
695 }, SystemAssemblyException.class);
699 container.connectExternalProvided(container.getProvidedInterfaces()
700 .get(0).getName(), env2.getName(), env2.getProvidedInterfaces()
703 Scope scope = container.start();
705 // check the value of the provided interface of the container
707 String value = scope.getInterfaceImplementation(container
708 .getProvidedInterfaces().get(0), String.class);
709 assertNotNull(value);
710 assertEquals(value, env2.getString());
711 assertFalse(value.equals(env1.getString()));
714 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 {
729 container.connectExternalProvided(container
730 .getProvidedInterfaces().get(0).getName()
731 + "xx", "env1", env1.getProvidedInterfaces().get(0)
734 }, SystemAssemblyException.class);
736 // Wrong provided interface name.
737 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
739 public void run() throws Exception {
740 container.connectExternalProvided(container
741 .getProvidedInterfaces().get(0).getName(), "env1", env1
742 .getProvidedInterfaces().get(0).getName()
745 }, SystemAssemblyException.class);
747 // Wrong provided component
748 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
750 public void run() throws Exception {
751 container.connectExternalProvided(container
752 .getProvidedInterfaces().get(0).getName(), "env3", env1
753 .getProvidedInterfaces().get(0).getName());
755 }, SystemAssemblyException.class);