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.ProvidedInterfaces;
35 import org.wamblee.system.core.RequiredInterface;
36 import org.wamblee.system.core.RequiredInterfaces;
37 import org.wamblee.system.core.Scope;
38 import org.wamblee.system.core.StringComponent;
39 import org.wamblee.system.core.SystemAssemblyException;
40 import org.wamblee.test.AssertionUtils;
41 import org.wamblee.test.EasyMockMatchers;
42 import org.wamblee.test.EventTracker;
44 public class ContainerTest extends TestCase {
46 private EventTracker<String> _tracker;
49 protected void setUp() throws Exception {
51 _tracker = new EventTracker<String>();
54 private static class MyMultiple implements Serializable, Runnable {
61 private List<Pair<ProvidedInterface, Component>> createProvidedInput(
62 ProvidedInterface[] aProvided, Component aProvider) {
63 List<Pair<ProvidedInterface, Component>> result = new ArrayList<Pair<ProvidedInterface, Component>>();
64 for (ProvidedInterface provided : aProvided) {
65 result.add(new Pair<ProvidedInterface, Component>(provided,
71 public void testEnvironmentApplication() {
72 Environment environment = new Environment(_tracker);
73 Application application = new Application(_tracker);
74 Container container = new Container("root", new Component[] {
75 environment, application }, new ProvidedInterface[0],
76 new RequiredInterface[0]);
77 Scope scope = container.start();
78 assertTrue(container.isSealed());
79 AssertionUtils.assertEquals(new String[] { "start.environment",
80 "start.application" }, _tracker.getEvents(
81 Thread.currentThread()).toArray(new String[0]));
82 assertEquals(0, scope.getProvidedInterfaces().size());
84 assertEquals(environment.getString(), application.getString());
85 assertEquals(environment.getInteger(), application.getInteger());
89 public void testEnvironmentApplicationSimpleConstructor() {
90 Environment environment = new Environment(_tracker);
91 Application application = new Application(_tracker);
92 Container container = new Container("root").addComponent(environment)
93 .addComponent(application);
95 Scope scope = container.start();
96 AssertionUtils.assertEquals(new String[] { "start.environment",
97 "start.application" }, _tracker.getEvents(
98 Thread.currentThread()).toArray(new String[0]));
99 assertEquals(0, scope.getProvidedInterfaces().size());
101 assertEquals(environment.getString(), application.getString());
102 assertEquals(environment.getInteger(), application.getInteger());
106 public void testApplicationEnvironment() {
108 Component<?> environment = new Environment();
109 Component<?> application = new Application();
110 Container container = new Container("root", new Component[] {
111 application, environment }, new ProvidedInterface[0],
112 new RequiredInterface[0]);
114 } catch (SystemAssemblyException e) {
115 // e.printStackTrace();
121 public void testComposite() {
122 Component<?> environment = new Environment(_tracker);
123 Component<?> application = new Application(_tracker);
124 assertEquals(0, _tracker.getEventCount());
126 Container system = new Container("all", new Component[] { environment,
127 application }, new ProvidedInterface[0],
128 new RequiredInterface[0]);
129 Scope runtime = system.start();
130 List<RequiredInterface> required = system.getRequiredInterfaces();
131 assertEquals(0, required.size());
132 List<ProvidedInterface> provided = system.getProvidedInterfaces();
133 assertEquals(0, provided.size());
135 AssertionUtils.assertEquals(new String[] { "start.environment",
136 "start.application" }, _tracker.getEvents(
137 Thread.currentThread()).toArray(new String[0]));
140 system.stop(runtime);
141 AssertionUtils.assertEquals(new String[] { "stop.application",
142 "stop.environment" }, _tracker
143 .getEvents(Thread.currentThread()).toArray(new String[0]));
147 public void testCompositeWithWrongProvidedInfo() {
149 Component<?> environment = new Environment();
150 Component<?> application = new Application();
151 Container system = new Container("all", new Component[] {
152 environment, application },
153 new ProvidedInterface[] { new DefaultProvidedInterface(
154 "float", Float.class) },
155 new DefaultRequiredInterface[0]);
157 } catch (SystemAssemblyException e) {
163 public void testCompositeRequiredInterfaceNotProvided() {
165 Component<?> environment = new Environment();
166 Component<?> application = new Application();
167 Container system = new Container("all", new Component[] {
168 environment, application }, new ProvidedInterface[0],
169 new RequiredInterface[] { new DefaultRequiredInterface(
170 "string", String.class) });
172 } catch (SystemAssemblyException e) {
178 public void testCompositeWithSuperfluousRequiredInfo() {
179 Component<?> environment = new Environment();
180 Component<?> application = new Application();
181 Container system = new Container("all", new Component[] { environment,
182 application }, new ProvidedInterface[0],
183 new RequiredInterface[] { new DefaultRequiredInterface("float",
185 system.getRequiredInterfaces().get(0)
186 .setProvider(new DefaultProvidedInterface("hallo", Float.class));
188 List<RequiredInterface> required = system.getRequiredInterfaces();
189 assertEquals(1, required.size());
190 List<ProvidedInterface> provided = system.getProvidedInterfaces();
191 assertEquals(0, provided.size());
194 public void testCompositeWithExternalDependencesNotProvided() {
196 Component<?> application = new Application();
198 Container system = new Container("all",
199 new Component[] { application }, new ProvidedInterface[0],
200 application.getRequiredInterfaces().toArray(new RequiredInterface[0]));
202 } catch (SystemAssemblyException e) {
208 public void testDuplicateComponent() {
210 Component<?> comp1 = new Application();
211 Component<?> comp2 = new Application();
212 Container system = new Container("top");
213 system.addComponent(comp1).addComponent(comp2);
214 } catch (SystemAssemblyException e) {
221 public void testInconsistentHierarchy() {
223 Component<?> comp = new Application();
224 Container system = new Container("top").addComponent(comp);
225 Container system2 = new Container("top2").addComponent(comp);
226 } catch (SystemAssemblyException e) {
232 public void testCompositeWithExternalDependencesProvided() {
234 Component<?> environment = new Environment();
235 Component<?> application = new Application();
236 Container system = new Container("all",
237 new Component[] { application }, new ProvidedInterface[0],
238 application.getRequiredInterfaces().toArray(new RequiredInterface[0]));
239 environment.start(new DefaultScope(new ProvidedInterface[0]));
240 system.getRequiredInterfaces().get(0).setProvider(environment
241 .getProvidedInterfaces().get(0));
242 system.getRequiredInterfaces().get(1).setProvider(environment
243 .getProvidedInterfaces().get(1));
246 List<RequiredInterface> required = system.getRequiredInterfaces();
247 assertEquals(2, required.size());
248 List<ProvidedInterface> provided = system.getProvidedInterfaces();
249 assertEquals(0, provided.size());
253 public void testAmbiguousInterfaces() {
255 Component<?> environment1 = new Environment();
256 Component<?> environment2 = new Environment();
257 Component<?> application = new Application();
258 Container container = new Container("root", new Component[] {
259 environment1, environment2, application },
260 new ProvidedInterface[0], new RequiredInterface[0]);
263 } catch (SystemAssemblyException e) {
269 public void testIncompleteRequirements() {
271 Component<?> application = new Application();
272 Container system = new Container("all",
273 new Component[] { application }, new ProvidedInterface[0],
274 new RequiredInterface[0]);
276 } catch (SystemAssemblyException e) {
282 public void testEnvironmentApplicationRollbackOnException()
284 IMocksControl control = EasyMock.createStrictControl();
286 Environment environment = new Environment(_tracker);
287 Application application = control.createMock(Application.class,
288 new ConstructorArgs(Application.class.getConstructor()),
289 Application.class.getDeclaredMethod("doStart", Scope.class));
291 application.doStart(EasyMockMatchers.anyObject(Scope.class));
292 EasyMock.expectLastCall().andThrow(new RuntimeException());
296 Container container = new Container("root", new Component[] {
297 environment, application }, new ProvidedInterface[0],
298 new RequiredInterface[0]);
301 } catch (RuntimeException e) {
302 AssertionUtils.assertEquals(new String[] { "start.environment",
303 "stop.environment" }, _tracker.getEvents(
304 Thread.currentThread()).toArray(new String[0]));
310 public void testEnvironmentApplicationRollbackOnExceptionWithExceptionOnStop()
312 IMocksControl control = EasyMock.createControl();
314 Environment environment = new Environment(_tracker);
315 // Application 1 will throw an exception while stopping.
316 Application application1 = control.createMock(Application.class,
317 new ConstructorArgs(Application.class.getConstructor()),
318 Application.class.getDeclaredMethod("doStop", Object.class));
320 application1.doStop(EasyMock.anyObject());
321 EasyMock.expectLastCall().andThrow(new RuntimeException());
323 // application 2 will throw an exception while starting
324 Application application2 = control.createMock(Application.class,
325 new ConstructorArgs(Application.class
326 .getConstructor(String.class), "application2"),
327 Application.class.getDeclaredMethod("doStart", Scope.class));
329 application2.doStart(EasyMockMatchers.anyObject(Scope.class));
330 EasyMock.expectLastCall().andThrow(new RuntimeException());
335 Container container = new Container("root", new Component[] {
336 environment, application1, application2 },
337 new ProvidedInterface[0], new RequiredInterface[0]);
340 } catch (RuntimeException e) {
341 AssertionUtils.assertEquals(new String[] { "start.environment",
342 "stop.environment" }, _tracker.getEvents(
343 Thread.currentThread()).toArray(new String[0]));
349 public void testOptionalRequiredInterfaceProvidedOptionalInternal() {
350 Application application = new Application(true);
351 Container container = new Container("top",
352 new Component[] { application }, new ProvidedInterface[0],
353 Application.required(true));
354 Environment env = new Environment();
355 container.getRequiredInterfaces().get(0).setProvider(env
356 .getProvidedInterfaces().get(0));
357 container.getRequiredInterfaces().get(1).setProvider(env
358 .getProvidedInterfaces().get(1));
359 Scope external = new DefaultScope(env.getProvidedInterfaces());
362 container.start(external);
363 assertSame(env.getProvidedInterfaces().get(0), container
364 .getRequiredInterfaces().get(0).getProvider());
365 assertSame(env.getProvidedInterfaces().get(1), container
366 .getRequiredInterfaces().get(1).getProvider());
367 assertSame(env.getProvidedInterfaces().get(0), application
368 .getRequiredInterfaces().get(0).getProvider());
369 assertSame(env.getProvidedInterfaces().get(1), application
370 .getRequiredInterfaces().get(1).getProvider());
373 public void testOptionalRequiredInterfaceNotProvidedOptionalInternal() {
374 Application application = new Application(true);
375 Container container = new Container("top",
376 new Component[] { application }, new ProvidedInterface[0],
377 Application.required(true));
378 Environment env = new Environment();
379 container.getRequiredInterfaces().get(0).setProvider(env
380 .getProvidedInterfaces().get(0));
381 Scope external = new DefaultScope(new ProvidedInterface[0]);
382 external.publishInterface(env.getProvidedInterfaces().get(0), env
384 container.start(external);
385 assertSame(env.getProvidedInterfaces().get(0), container
386 .getRequiredInterfaces().get(0).getProvider());
387 assertNull(container.getRequiredInterfaces().get(1).getProvider());
388 assertSame(env.getProvidedInterfaces().get(0), application
389 .getRequiredInterfaces().get(0).getProvider());
390 assertNull(application.getRequiredInterfaces().get(1).getProvider());
393 public void testOptionalRequiredInterfaceProvidedMandatoryInternal() {
394 Application application = new Application();
395 Container container = new Container("top",
396 new Component[] { application }, new ProvidedInterface[0],
397 Application.required(true));
398 Environment env = new Environment();
399 container.getRequiredInterfaces().get(0).setProvider(env
400 .getProvidedInterfaces().get(0));
401 container.getRequiredInterfaces().get(1).setProvider(env
402 .getProvidedInterfaces().get(1));
405 } catch (SystemAssemblyException e) {
411 public void testSealed() {
412 final Container container = new Container("xx");
413 assertFalse(container.isSealed());
415 assertTrue(container.isSealed());
417 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
419 public void run() throws Exception {
420 container.addComponent(new Application());
422 }, SystemAssemblyException.class);
424 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
426 public void run() throws Exception {
427 container.connectRequiredProvided("x", "y", "a", "b");
429 }, SystemAssemblyException.class);
430 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
432 public void run() throws Exception {
433 container.connectExternalRequired("x", "y", "a");
435 }, SystemAssemblyException.class);
436 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
438 public void run() throws Exception {
439 container.connectExternalProvided("x", "y", "z");
441 }, SystemAssemblyException.class);
442 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
444 public void run() throws Exception {
445 container.addProvidedInterface(new DefaultProvidedInterface(
446 "xx", String.class));
448 }, SystemAssemblyException.class);
450 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
452 public void run() throws Exception {
453 container.addRequiredInterface(new DefaultRequiredInterface(
454 "xx", String.class));
456 }, SystemAssemblyException.class);
459 public void testRestriction() {
460 Environment env1 = new Environment("env1");
461 Environment env2 = new Environment("env2");
462 Application app = new Application("app");
463 Container container = new Container("top").addComponent(env1)
464 .addComponent(env2).addComponent(app);
465 container.connectRequiredProvided("app", null, "env1", null);
467 assertEquals(env1.getString(), app.getString());
468 assertFalse(env2.getString().equals(app.getString()));
471 public void testProvidedInDifferentScopes() {
472 // Scoping problem occurred. Externally and internally provided
473 // components clashed
474 // because unique id generation in the scope was wrong.
476 StringComponent str = new StringComponent("string");
477 Application app = new Application("app");
478 Container container = new Container("top").addComponent(str)
480 container.addRequiredInterface(new DefaultRequiredInterface("integer",
483 ProvidedInterface provided = new DefaultProvidedInterface("hallo",
485 container.getRequiredInterfaces().get(0).setProvider(provided);
487 Scope external = new DefaultScope(new ProvidedInterface[0]);
488 external.publishInterface(provided, 100);
489 Scope scope = container.start(external);
492 public void testProvidedInterfaces() {
493 Environment env = new Environment(_tracker);
494 Container envcontainer = new Container("0").addComponent(env)
495 .addProvidedInterface(
496 new DefaultProvidedInterface("string", String.class))
497 .addProvidedInterface(
498 new DefaultProvidedInterface("integer", Integer.class));
499 Scope scope = envcontainer.start();
501 AssertionUtils.assertEquals(new String[] { "start.environment" },
502 _tracker.getEvents(Thread.currentThread()).toArray(
505 envcontainer.stop(scope);
508 public void testCoupleTwoContainers() {
509 Environment env = new Environment(_tracker);
510 Container envcontainer = new Container("0").addComponent(env)
511 .addProvidedInterface(
512 new DefaultProvidedInterface("string", String.class))
513 .addProvidedInterface(
514 new DefaultProvidedInterface("integer", Integer.class));
516 Application app = new Application(_tracker);
517 Container appcontainer = new Container("1").addComponent(app)
518 .addRequiredInterface(
519 new DefaultRequiredInterface("string", String.class))
520 .addRequiredInterface(
521 new DefaultRequiredInterface("integer", Integer.class));
523 Container top = new Container("top");
524 top.addComponent(envcontainer).addComponent(appcontainer);
527 AssertionUtils.assertEquals(new String[] { "start.environment",
528 "start.application" }, _tracker.getEvents(
529 Thread.currentThread()).toArray(new String[0]));
533 public void testNonUniqueRequiredInterface() {
534 final Container container = new Container("top");
535 container.addRequiredInterface(new DefaultRequiredInterface("i",
537 container.addRequiredInterface(new DefaultRequiredInterface("x",
539 container.addRequiredInterface(new DefaultRequiredInterface("y",
542 Application app = new Application("1");
543 container.addComponent(app);
545 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
547 public void run() throws Exception {
550 }, SystemAssemblyException.class);
552 container.connectExternalRequired("1", app.getRequiredInterfaces().get(0)
555 ProvidedInterface i = new DefaultProvidedInterface("i", Integer.class);
556 ProvidedInterface x = new DefaultProvidedInterface("x", String.class);
557 ProvidedInterface y = new DefaultProvidedInterface("y", String.class);
559 Scope externalScope = new DefaultScope(new ProvidedInterface[0]);
561 externalScope.publishInterface(i, 100);
562 externalScope.publishInterface(x, "x-value");
563 externalScope.publishInterface(y, "y-value");
565 container.getRequiredInterfaces().get(0).setProvider(i);
566 container.getRequiredInterfaces().get(1).setProvider(x);
567 container.getRequiredInterfaces().get(2).setProvider(y);
569 Scope runtime = container.start(externalScope);
571 assertEquals("y-value", app.getString());
575 public void testNonUniqueProvidedInterface() {
577 final Container container = new Container("top")
578 .addProvidedInterface(new DefaultProvidedInterface("external",
580 Environment env1 = new Environment("env1");
581 Environment env2 = new Environment("env2");
583 container.addComponent(env1);
584 container.addComponent(env2);
586 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
588 public void run() throws Exception {
591 }, SystemAssemblyException.class);
595 container.connectExternalProvided(container.getProvidedInterfaces().get(0)
596 .getName(), env2.getName(), env2.getProvidedInterfaces().get(0)
599 Scope scope = container.start();
601 // check the value of the provided interface of the container
603 String value = scope.getInterfaceImplementation(container
604 .getProvidedInterfaces().get(0), String.class);
605 assertNotNull(value);
606 assertEquals(value, env2.getString());
607 assertFalse(value.equals(env1.getString()));