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.core;
18 import java.io.IOException;
19 import java.io.Serializable;
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.List;
24 import junit.framework.TestCase;
26 import org.easymock.classextension.ConstructorArgs;
27 import org.easymock.classextension.EasyMock;
28 import org.easymock.classextension.IMocksControl;
29 import org.wamblee.general.Pair;
30 import org.wamblee.test.AssertionUtils;
31 import org.wamblee.test.EasyMockMatchers;
32 import org.wamblee.test.EventTracker;
34 public class ContainerTest extends TestCase {
36 private EventTracker<String> _tracker;
39 protected void setUp() throws Exception {
41 _tracker = new EventTracker<String>();
44 private static class MyMultiple implements Serializable, Runnable {
51 private List<Pair<ProvidedInterface, Component>> createProvidedInput(
52 ProvidedInterface[] aProvided, Component aProvider) {
53 List<Pair<ProvidedInterface, Component>> result = new ArrayList<Pair<ProvidedInterface, Component>>();
54 for (ProvidedInterface provided : aProvided) {
55 result.add(new Pair<ProvidedInterface, Component>(provided,
61 public void testFilterProvided() {
62 RequiredInterface req1 = new DefaultRequiredInterface("name",
64 RequiredInterface req2 = new DefaultRequiredInterface("name",
66 ProvidedInterface prov1 = new DefaultProvidedInterface("name",
68 ProvidedInterface prov2 = new DefaultProvidedInterface("name",
70 ProvidedInterface prov3 = new DefaultProvidedInterface("name",
73 Component client = new Application("client");
74 Component dummy = new Application("dummy");
76 InterfaceRestriction noRestriction = new InterfaceRestriction() {
78 public boolean isViolated(Component aClient,
79 RequiredInterface aRequired, Component aServer,
80 ProvidedInterface aProvided) {
85 AssertionUtils.assertEquals(new ProvidedInterface[] { prov1 },
86 Container.filterProvidedServices(client, req1,
87 createProvidedInput(new ProvidedInterface[] { prov1 },
88 dummy), noRestriction));
89 AssertionUtils.assertEquals(new ProvidedInterface[] { prov1 },
90 Container.filterProvidedServices(client, req1,
91 createProvidedInput(new ProvidedInterface[] { prov1,
92 prov2 }, dummy), noRestriction));
93 AssertionUtils.assertEquals(new ProvidedInterface[] { prov1, prov3 },
94 Container.filterProvidedServices(client, req1,
95 createProvidedInput(new ProvidedInterface[] { prov1,
96 prov3 }, dummy), noRestriction));
98 InterfaceRestriction everything = new InterfaceRestriction() {
100 public boolean isViolated(Component aClient,
101 RequiredInterface aRequired, Component aServer,
102 ProvidedInterface aProvided) {
106 AssertionUtils.assertEquals(new ProvidedInterface[0], Container
107 .filterProvidedServices(client, req1, createProvidedInput(
108 new ProvidedInterface[] { prov1, prov3 }, dummy),
113 public void testEnvironmentApplication() {
114 Environment environment = new Environment(_tracker);
115 Application application = new Application(_tracker);
116 Container container = new Container("root", new Component[] {
117 environment, application }, new ProvidedInterface[0],
118 new RequiredInterface[0]);
119 Scope scope = container.start();
120 assertTrue(container.isSealed());
121 AssertionUtils.assertEquals(new String[] { "start.environment",
122 "start.application" }, _tracker.getEvents(
123 Thread.currentThread()).toArray(new String[0]));
124 assertEquals(0, scope.getProvidedInterfaces().length);
126 assertEquals(environment.getString(), application.getString());
127 assertEquals(environment.getInteger(), application.getInteger());
131 public void testEnvironmentApplicationSimpleConstructor() {
132 Environment environment = new Environment(_tracker);
133 Application application = new Application(_tracker);
134 Container container = new Container("root").addComponent(environment)
135 .addComponent(application);
137 Scope scope = container.start();
138 AssertionUtils.assertEquals(new String[] { "start.environment",
139 "start.application" }, _tracker.getEvents(
140 Thread.currentThread()).toArray(new String[0]));
141 assertEquals(0, scope.getProvidedInterfaces().length);
143 assertEquals(environment.getString(), application.getString());
144 assertEquals(environment.getInteger(), application.getInteger());
148 public void testApplicationEnvironment() {
150 Component environment = new Environment();
151 Component application = new Application();
152 Container container = new Container("root", new Component[] {
153 application, environment }, new ProvidedInterface[0],
154 new RequiredInterface[0]);
156 } catch (SystemAssemblyException e) {
157 // e.printStackTrace();
163 public void testComposite() {
164 Component environment = new Environment(_tracker);
165 Component application = new Application(_tracker);
166 assertEquals(0, _tracker.getEventCount());
168 Container system = new Container("all", new Component[] { environment,
169 application }, new ProvidedInterface[0],
170 new RequiredInterface[0]);
171 Scope runtime = system.start();
172 RequiredInterface[] required = system.getRequiredInterfaces();
173 assertEquals(0, required.length);
174 ProvidedInterface[] provided = system.getProvidedInterfaces();
175 assertEquals(0, provided.length);
177 AssertionUtils.assertEquals(new String[] { "start.environment",
178 "start.application" }, _tracker.getEvents(
179 Thread.currentThread()).toArray(new String[0]));
182 system.stop(runtime);
183 AssertionUtils.assertEquals(new String[] { "stop.application",
184 "stop.environment" }, _tracker
185 .getEvents(Thread.currentThread()).toArray(new String[0]));
189 public void testCompositeWithWrongProvidedInfo() {
191 Component environment = new Environment();
192 Component application = new Application();
193 Container system = new Container("all", new Component[] {
194 environment, application },
195 new ProvidedInterface[] { new DefaultProvidedInterface(
196 "float", Float.class) },
197 new DefaultRequiredInterface[0]);
199 } catch (SystemAssemblyException e) {
205 public void testCompositeRequiredInterfaceNotProvided() {
207 Component environment = new Environment();
208 Component application = new Application();
209 Container system = new Container("all", new Component[] {
210 environment, application }, new ProvidedInterface[0],
211 new RequiredInterface[] { new DefaultRequiredInterface(
212 "string", String.class) });
214 } catch (SystemAssemblyException e) {
220 public void testCompositeWithSuperfluousRequiredInfo() {
221 Component environment = new Environment();
222 Component application = new Application();
223 Container system = new Container("all", new Component[] { environment,
224 application }, new ProvidedInterface[0],
225 new RequiredInterface[] { new DefaultRequiredInterface("float",
227 system.getRequiredInterfaces()[0]
228 .setProvider(new DefaultProvidedInterface("hallo", Float.class));
230 RequiredInterface[] required = system.getRequiredInterfaces();
231 assertEquals(1, required.length);
232 ProvidedInterface[] provided = system.getProvidedInterfaces();
233 assertEquals(0, provided.length);
236 public void testCompositeWithExternalDependencesNotProvided() {
238 Component environment = new Environment();
239 Component application = new Application();
240 Container system = new Container("all",
241 new Component[] { application }, new ProvidedInterface[0],
242 application.getRequiredInterfaces());
244 } catch (SystemAssemblyException e) {
251 public void testDuplicateComponent() {
253 Component comp1 = new Application();
254 Component comp2 = new Application();
255 Container system = new Container("top");
256 system.addComponent(comp1).addComponent(comp2);
257 } catch (SystemAssemblyException e) {
263 public void testInconsistentHierarchy() {
265 Component comp = new Application();
266 Container system = new Container("top").addComponent(comp);
267 Container system2 = new Container("top2").addComponent(comp);
268 } catch (SystemAssemblyException e) {
274 public void testCompositeWithExternalDependencesProvided() {
276 Component environment = new Environment();
277 Component application = new Application();
278 Container system = new Container("all",
279 new Component[] { application }, new ProvidedInterface[0],
280 application.getRequiredInterfaces());
281 environment.start(new DefaultScope(new ProvidedInterface[0]));
282 system.getRequiredInterfaces()[0].setProvider(environment
283 .getProvidedInterfaces()[0]);
284 system.getRequiredInterfaces()[1].setProvider(environment
285 .getProvidedInterfaces()[1]);
288 RequiredInterface[] required = system.getRequiredInterfaces();
289 assertEquals(2, required.length);
290 ProvidedInterface[] provided = system.getProvidedInterfaces();
291 assertEquals(0, provided.length);
295 public void testAmbiguousInterfaces() {
297 Component environment1 = new Environment();
298 Component environment2 = new Environment();
299 Component application = new Application();
300 Container container = new Container("root", new Component[] {
301 environment1, environment2, application },
302 new ProvidedInterface[0], new RequiredInterface[0]);
305 } catch (SystemAssemblyException e) {
311 public void testIncompleteRequirements() {
313 Component application = new Application();
314 Container system = new Container("all",
315 new Component[] { application }, new ProvidedInterface[0],
316 new RequiredInterface[0]);
318 } catch (SystemAssemblyException e) {
324 public void testEnvironmentApplicationRollbackOnException()
326 IMocksControl control = EasyMock.createStrictControl();
328 Environment environment = new Environment(_tracker);
329 Application application = control.createMock(Application.class,
330 new ConstructorArgs(Application.class.getConstructor()),
331 Application.class.getDeclaredMethod("doStart", Scope.class));
333 application.doStart(EasyMockMatchers.anyObject(Scope.class));
334 EasyMock.expectLastCall().andThrow(new RuntimeException());
338 Container container = new Container("root", new Component[] {
339 environment, application }, new ProvidedInterface[0],
340 new RequiredInterface[0]);
343 } catch (RuntimeException e) {
344 AssertionUtils.assertEquals(new String[] { "start.environment",
345 "stop.environment" }, _tracker.getEvents(
346 Thread.currentThread()).toArray(new String[0]));
352 public void testEnvironmentApplicationRollbackOnExceptionWithExceptionOnStop()
354 IMocksControl control = EasyMock.createControl();
356 Environment environment = new Environment(_tracker);
357 // Application 1 will throw an exception while stopping.
358 Application application1 = control.createMock(Application.class,
359 new ConstructorArgs(Application.class.getConstructor()),
360 Application.class.getDeclaredMethod("doStop", Object.class));
362 application1.doStop(EasyMock.anyObject());
363 EasyMock.expectLastCall().andThrow(new RuntimeException());
365 // application 2 will throw an exception while starting
366 Application application2 = control.createMock(Application.class,
367 new ConstructorArgs(Application.class
368 .getConstructor(String.class), "application2"),
369 Application.class.getDeclaredMethod("doStart", Scope.class));
371 application2.doStart(EasyMockMatchers.anyObject(Scope.class));
372 EasyMock.expectLastCall().andThrow(new RuntimeException());
377 Container container = new Container("root", new Component[] {
378 environment, application1, application2 },
379 new ProvidedInterface[0], new RequiredInterface[0]);
382 } catch (RuntimeException e) {
383 AssertionUtils.assertEquals(new String[] { "start.environment",
384 "stop.environment" }, _tracker.getEvents(
385 Thread.currentThread()).toArray(new String[0]));
391 public void testOptionalRequiredInterfaceProvidedOptionalInternal() {
392 Application application = new Application(true);
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()[0].setProvider(env
398 .getProvidedInterfaces()[0]);
399 container.getRequiredInterfaces()[1].setProvider(env
400 .getProvidedInterfaces()[1]);
401 Scope external = new DefaultScope(env.getProvidedInterfaces());
404 container.start(external);
405 assertSame(env.getProvidedInterfaces()[0], container
406 .getRequiredInterfaces()[0].getProvider());
407 assertSame(env.getProvidedInterfaces()[1], container
408 .getRequiredInterfaces()[1].getProvider());
409 assertSame(env.getProvidedInterfaces()[0], application
410 .getRequiredInterfaces()[0].getProvider());
411 assertSame(env.getProvidedInterfaces()[1], application
412 .getRequiredInterfaces()[1].getProvider());
415 public void testOptionalRequiredInterfaceNotProvidedOptionalInternal() {
416 Application application = new Application(true);
417 Container container = new Container("top",
418 new Component[] { application }, new ProvidedInterface[0],
419 Application.required(true));
420 Environment env = new Environment();
421 container.getRequiredInterfaces()[0].setProvider(env
422 .getProvidedInterfaces()[0]);
423 Scope external = new DefaultScope(new ProvidedInterface[0]);
424 external.publishInterface(env.getProvidedInterfaces()[0], env
426 container.start(external);
427 assertSame(env.getProvidedInterfaces()[0], container
428 .getRequiredInterfaces()[0].getProvider());
429 assertNull(container.getRequiredInterfaces()[1].getProvider());
430 assertSame(env.getProvidedInterfaces()[0], application
431 .getRequiredInterfaces()[0].getProvider());
432 assertNull(application.getRequiredInterfaces()[1].getProvider());
435 public void testOptionalRequiredInterfaceProvidedMandatoryInternal() {
436 Application application = new Application();
437 Container container = new Container("top",
438 new Component[] { application }, new ProvidedInterface[0],
439 Application.required(true));
440 Environment env = new Environment();
441 container.getRequiredInterfaces()[0].setProvider(env
442 .getProvidedInterfaces()[0]);
443 container.getRequiredInterfaces()[1].setProvider(env
444 .getProvidedInterfaces()[1]);
446 assertSame(env.getProvidedInterfaces()[0], container
447 .getRequiredInterfaces()[0].getProvider());
448 assertSame(env.getProvidedInterfaces()[1], container
449 .getRequiredInterfaces()[1].getProvider());
450 assertSame(env.getProvidedInterfaces()[0], application
451 .getRequiredInterfaces()[0].getProvider());
452 assertSame(env.getProvidedInterfaces()[1], application
453 .getRequiredInterfaces()[1].getProvider());
456 public void testSealed() {
457 final Container container = new Container("xx");
458 assertFalse(container.isSealed());
460 assertTrue(container.isSealed());
462 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
464 public void run() throws Exception {
465 container.addComponent(new Application());
467 }, SystemAssemblyException.class);
469 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
471 public void run() throws Exception {
472 container.addRestriction(new InterfaceRestriction() {
474 public boolean isViolated(Component aClient,
475 RequiredInterface aRequired, Component aServer,
476 ProvidedInterface aProvided) {
481 }, SystemAssemblyException.class);
482 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
484 public void run() throws Exception {
485 container.addProvidedInterface(new DefaultProvidedInterface(
486 "xx", String.class));
488 }, SystemAssemblyException.class);
490 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
492 public void run() throws Exception {
493 container.addRequiredInterface(new DefaultRequiredInterface(
494 "xx", String.class));
496 }, SystemAssemblyException.class);
499 public void testRestriction() {
500 Environment env1 = new Environment("env1");
501 Environment env2 = new Environment("env2");
502 Application app = new Application("app");
503 Container container = new Container("top").addComponent(env1)
504 .addComponent(env2).addComponent(app);
505 container.addRestriction(new DefaultInterfaceRestriction("app", null,
508 assertEquals(env1.getString(), app.getString());
509 assertFalse(env2.getString().equals(app.getString()));
512 public void testProvidedInDifferentScopes() {
513 // Scoping problem occurred. Externally and internally provided
514 // components clashed
515 // because unique id generation in the scope was wrong.
517 StringComponent str = new StringComponent("string");
518 Application app = new Application("app");
519 Container container = new Container("top").addComponent(str)
521 container.addRequiredInterface(new DefaultRequiredInterface("integer",
524 ProvidedInterface provided = new DefaultProvidedInterface("hallo",
526 container.getRequiredInterfaces()[0].setProvider(provided);
528 Scope external = new DefaultScope(new ProvidedInterface[0]);
529 external.publishInterface(provided, 100);
530 Scope scope = container.start(external);
533 public void testProvidedInterfaces() {
534 Environment env = new Environment(_tracker);
535 Container envcontainer = new Container("0").addComponent(env)
536 .addProvidedInterface(
537 new DefaultProvidedInterface("string", String.class))
538 .addProvidedInterface(
539 new DefaultProvidedInterface("integer", Integer.class));
540 Scope scope = envcontainer.start();
542 AssertionUtils.assertEquals(new String[] { "start.environment" },
543 _tracker.getEvents(Thread.currentThread()).toArray(
546 envcontainer.stop(scope);
549 public void testCoupleTwoContainers() {
550 Environment env = new Environment(_tracker);
551 Container envcontainer = new Container("0").addComponent(env)
552 .addProvidedInterface(
553 new DefaultProvidedInterface("string", String.class))
554 .addProvidedInterface(
555 new DefaultProvidedInterface("integer", Integer.class));
557 Application app = new Application(_tracker);
558 Container appcontainer = new Container("1").addComponent(app)
559 .addRequiredInterface(
560 new DefaultRequiredInterface("string", String.class))
561 .addRequiredInterface(
562 new DefaultRequiredInterface("integer", Integer.class));
564 Container top = new Container("top");
565 top.addComponent(envcontainer).addComponent(appcontainer);
568 AssertionUtils.assertEquals(new String[] { "start.environment", "start.application" },
569 _tracker.getEvents(Thread.currentThread()).toArray(