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)
184 .setProvider(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(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) {
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(new RequiredInterface[0]));
237 environment.start(new DefaultScope(new ProvidedInterface[0]));
238 system.getRequiredInterfaces().get(0).setProvider(environment
239 .getProvidedInterfaces().get(0));
240 system.getRequiredInterfaces().get(1).setProvider(environment
241 .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 IMocksControl control = EasyMock.createStrictControl();
284 Environment environment = new Environment(_tracker);
285 Application application = control.createMock(Application.class,
286 new ConstructorArgs(Application.class.getConstructor()),
287 Application.class.getDeclaredMethod("doStart", Scope.class));
289 application.doStart(EasyMockMatchers.anyObject(Scope.class));
290 EasyMock.expectLastCall().andThrow(new RuntimeException());
294 Container container = new Container("root", new Component[] {
295 environment, application }, new ProvidedInterface[0],
296 new RequiredInterface[0]);
299 } catch (RuntimeException e) {
300 AssertionUtils.assertEquals(new String[] { "start.environment",
301 "stop.environment" }, _tracker.getEvents(
302 Thread.currentThread()).toArray(new String[0]));
308 public void testEnvironmentApplicationRollbackOnExceptionWithExceptionOnStop()
310 IMocksControl control = EasyMock.createControl();
312 Environment environment = new Environment(_tracker);
313 // Application 1 will throw an exception while stopping.
314 Application application1 = control.createMock(Application.class,
315 new ConstructorArgs(Application.class.getConstructor()),
316 Application.class.getDeclaredMethod("doStop", Object.class));
318 application1.doStop(EasyMock.anyObject());
319 EasyMock.expectLastCall().andThrow(new RuntimeException());
321 // application 2 will throw an exception while starting
322 Application application2 = control.createMock(Application.class,
323 new ConstructorArgs(Application.class
324 .getConstructor(String.class), "application2"),
325 Application.class.getDeclaredMethod("doStart", Scope.class));
327 application2.doStart(EasyMockMatchers.anyObject(Scope.class));
328 EasyMock.expectLastCall().andThrow(new RuntimeException());
333 Container container = new Container("root", new Component[] {
334 environment, application1, application2 },
335 new ProvidedInterface[0], new RequiredInterface[0]);
338 } catch (RuntimeException e) {
339 AssertionUtils.assertEquals(new String[] { "start.environment",
340 "stop.environment" }, _tracker.getEvents(
341 Thread.currentThread()).toArray(new String[0]));
347 public void testOptionalRequiredInterfaceProvidedOptionalInternal() {
348 Application application = new Application(true);
349 Container container = new Container("top",
350 new Component[] { application }, new ProvidedInterface[0],
351 Application.required(true));
352 Environment env = new Environment();
353 container.getRequiredInterfaces().get(0).setProvider(env
354 .getProvidedInterfaces().get(0));
355 container.getRequiredInterfaces().get(1).setProvider(env
356 .getProvidedInterfaces().get(1));
357 Scope external = new DefaultScope(env.getProvidedInterfaces());
360 container.start(external);
361 assertSame(env.getProvidedInterfaces().get(0), container
362 .getRequiredInterfaces().get(0).getProvider());
363 assertSame(env.getProvidedInterfaces().get(1), container
364 .getRequiredInterfaces().get(1).getProvider());
365 assertSame(env.getProvidedInterfaces().get(0), application
366 .getRequiredInterfaces().get(0).getProvider());
367 assertSame(env.getProvidedInterfaces().get(1), application
368 .getRequiredInterfaces().get(1).getProvider());
371 public void testOptionalRequiredInterfaceNotProvidedOptionalInternal() {
372 Application application = new Application(true);
373 Container container = new Container("top",
374 new Component[] { application }, new ProvidedInterface[0],
375 Application.required(true));
376 Environment env = new Environment();
377 container.getRequiredInterfaces().get(0).setProvider(env
378 .getProvidedInterfaces().get(0));
379 Scope external = new DefaultScope(new ProvidedInterface[0]);
380 external.publishInterface(env.getProvidedInterfaces().get(0), env
382 container.start(external);
383 assertSame(env.getProvidedInterfaces().get(0), container
384 .getRequiredInterfaces().get(0).getProvider());
385 assertNull(container.getRequiredInterfaces().get(1).getProvider());
386 assertSame(env.getProvidedInterfaces().get(0), application
387 .getRequiredInterfaces().get(0).getProvider());
388 assertNull(application.getRequiredInterfaces().get(1).getProvider());
391 public void testOptionalRequiredInterfaceProvidedMandatoryInternal() {
392 Application application = new Application();
393 Container container = new Container("top",
394 new Component[] { application }, new ProvidedInterface[0],
395 Application.required(true));
396 Environment env = new Environment();
397 container.getRequiredInterfaces().get(0).setProvider(env
398 .getProvidedInterfaces().get(0));
399 container.getRequiredInterfaces().get(1).setProvider(env
400 .getProvidedInterfaces().get(1));
403 } catch (SystemAssemblyException e) {
409 public void testSealed() {
410 final Container container = new Container("xx");
411 assertFalse(container.isSealed());
413 assertTrue(container.isSealed());
415 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
417 public void run() throws Exception {
418 container.addComponent(new Application());
420 }, SystemAssemblyException.class);
422 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
424 public void run() throws Exception {
425 container.connectRequiredProvided("x", "y", "a", "b");
427 }, SystemAssemblyException.class);
428 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
430 public void run() throws Exception {
431 container.connectExternalRequired("x", "y", "a");
433 }, SystemAssemblyException.class);
434 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
436 public void run() throws Exception {
437 container.connectExternalProvided("x", "y", "z");
439 }, SystemAssemblyException.class);
440 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
442 public void run() throws Exception {
443 container.addProvidedInterface(new DefaultProvidedInterface(
444 "xx", String.class));
446 }, SystemAssemblyException.class);
448 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
450 public void run() throws Exception {
451 container.addRequiredInterface(new DefaultRequiredInterface(
452 "xx", String.class));
454 }, SystemAssemblyException.class);
457 public void testRestriction() {
458 Environment env1 = new Environment("env1");
459 Environment env2 = new Environment("env2");
460 Application app = new Application("app");
461 Container container = new Container("top").addComponent(env1)
462 .addComponent(env2).addComponent(app);
463 container.connectRequiredProvided("app", null, "env1", null);
465 assertEquals(env1.getString(), app.getString());
466 assertFalse(env2.getString().equals(app.getString()));
469 public void testProvidedInDifferentScopes() {
470 // Scoping problem occurred. Externally and internally provided
471 // components clashed
472 // because unique id generation in the scope was wrong.
474 StringComponent str = new StringComponent("string");
475 Application app = new Application("app");
476 Container container = new Container("top").addComponent(str)
478 container.addRequiredInterface(new DefaultRequiredInterface("integer",
481 ProvidedInterface provided = new DefaultProvidedInterface("hallo",
483 container.getRequiredInterfaces().get(0).setProvider(provided);
485 Scope external = new DefaultScope(new ProvidedInterface[0]);
486 external.publishInterface(provided, 100);
487 Scope scope = container.start(external);
490 public void testProvidedInterfaces() {
491 Environment env = new Environment(_tracker);
492 Container envcontainer = new Container("0").addComponent(env)
493 .addProvidedInterface(
494 new DefaultProvidedInterface("string", String.class))
495 .addProvidedInterface(
496 new DefaultProvidedInterface("integer", Integer.class));
497 Scope scope = envcontainer.start();
499 AssertionUtils.assertEquals(new String[] { "start.environment" },
500 _tracker.getEvents(Thread.currentThread()).toArray(
503 envcontainer.stop(scope);
506 public void testCoupleTwoContainers() {
507 Environment env = new Environment(_tracker);
508 Container envcontainer = new Container("0").addComponent(env)
509 .addProvidedInterface(
510 new DefaultProvidedInterface("string", String.class))
511 .addProvidedInterface(
512 new DefaultProvidedInterface("integer", Integer.class));
514 Application app = new Application(_tracker);
515 Container appcontainer = new Container("1").addComponent(app)
516 .addRequiredInterface(
517 new DefaultRequiredInterface("string", String.class))
518 .addRequiredInterface(
519 new DefaultRequiredInterface("integer", Integer.class));
521 Container top = new Container("top");
522 top.addComponent(envcontainer).addComponent(appcontainer);
525 AssertionUtils.assertEquals(new String[] { "start.environment",
526 "start.application" }, _tracker.getEvents(
527 Thread.currentThread()).toArray(new String[0]));
531 public void testNonUniqueRequiredInterface() {
532 final Container container = new Container("top");
533 container.addRequiredInterface(new DefaultRequiredInterface("i",
535 container.addRequiredInterface(new DefaultRequiredInterface("x",
537 container.addRequiredInterface(new DefaultRequiredInterface("y",
540 Application app = new Application("1");
541 container.addComponent(app);
543 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
545 public void run() throws Exception {
548 }, SystemAssemblyException.class);
550 container.connectExternalRequired("1", app.getRequiredInterfaces().get(0)
553 ProvidedInterface i = new DefaultProvidedInterface("i", Integer.class);
554 ProvidedInterface x = new DefaultProvidedInterface("x", String.class);
555 ProvidedInterface y = new DefaultProvidedInterface("y", String.class);
557 Scope externalScope = new DefaultScope(new ProvidedInterface[0]);
559 externalScope.publishInterface(i, 100);
560 externalScope.publishInterface(x, "x-value");
561 externalScope.publishInterface(y, "y-value");
563 container.getRequiredInterfaces().get(0).setProvider(i);
564 container.getRequiredInterfaces().get(1).setProvider(x);
565 container.getRequiredInterfaces().get(2).setProvider(y);
567 Scope runtime = container.start(externalScope);
569 assertEquals("y-value", app.getString());
573 public void testNonUniqueProvidedInterface() {
575 final Container container = new Container("top")
576 .addProvidedInterface(new DefaultProvidedInterface("external",
578 Environment env1 = new Environment("env1");
579 Environment env2 = new Environment("env2");
581 container.addComponent(env1);
582 container.addComponent(env2);
584 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
586 public void run() throws Exception {
589 }, SystemAssemblyException.class);
593 container.connectExternalProvided(container.getProvidedInterfaces().get(0)
594 .getName(), env2.getName(), env2.getProvidedInterfaces().get(0)
597 Scope scope = container.start();
599 // check the value of the provided interface of the container
601 String value = scope.getInterfaceImplementation(container
602 .getProvidedInterfaces().get(0), String.class);
603 assertNotNull(value);
604 assertEquals(value, env2.getString());
605 assertFalse(value.equals(env1.getString()));