(no commit message)
[utils] / system / general / src / test / java / org / wamblee / system / container / ContainerTest.java
1 /*
2  * Copyright 2007 the original author or authors.
3  * 
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
7  * 
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  * 
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.
15  */
16 package org.wamblee.system.container;
17
18 import java.io.Serializable;
19 import java.util.ArrayList;
20 import java.util.List;
21
22 import junit.framework.TestCase;
23
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;
41
42 public class ContainerTest extends TestCase {
43
44     private EventTracker<String> _tracker;
45
46     @Override
47     protected void setUp() throws Exception {
48         super.setUp();
49         _tracker = new EventTracker<String>();
50     }
51
52     private static class MyMultiple implements Serializable, Runnable {
53         @Override
54         public void run() {
55             // Empty
56         }
57     }
58
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,
64                     aProvider));
65         }
66         return result;
67     }
68
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().length);
81
82         assertEquals(environment.getString(), application.getString());
83         assertEquals(environment.getInteger(), application.getInteger());
84
85     }
86
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);
92
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().length);
98
99         assertEquals(environment.getString(), application.getString());
100         assertEquals(environment.getInteger(), application.getInteger());
101
102     }
103
104     public void testApplicationEnvironment() {
105         try {
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]);
111             container.start();
112         } catch (SystemAssemblyException e) {
113             // e.printStackTrace();
114             return;
115         }
116         fail();
117     }
118
119     public void testComposite() {
120         Component environment = new Environment(_tracker);
121         Component application = new Application(_tracker);
122         assertEquals(0, _tracker.getEventCount());
123
124         Container system = new Container("all", new Component[] { environment,
125                 application }, new ProvidedInterface[0],
126                 new RequiredInterface[0]);
127         Scope runtime = system.start();
128         RequiredInterface[] required = system.getRequiredInterfaces();
129         assertEquals(0, required.length);
130         ProvidedInterface[] provided = system.getProvidedInterfaces();
131         assertEquals(0, provided.length);
132
133         AssertionUtils.assertEquals(new String[] { "start.environment",
134                 "start.application" }, _tracker.getEvents(
135                 Thread.currentThread()).toArray(new String[0]));
136         _tracker.clear();
137
138         system.stop(runtime);
139         AssertionUtils.assertEquals(new String[] { "stop.application",
140                 "stop.environment" }, _tracker
141                 .getEvents(Thread.currentThread()).toArray(new String[0]));
142
143     }
144
145     public void testCompositeWithWrongProvidedInfo() {
146         try {
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]);
154             system.validate();
155         } catch (SystemAssemblyException e) {
156             return;
157         }
158         fail();
159     }
160
161     public void testCompositeRequiredInterfaceNotProvided() {
162         try {
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) });
169             system.start();
170         } catch (SystemAssemblyException e) {
171             return;
172         }
173         fail();
174     }
175
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",
182                         Float.class) });
183         system.getRequiredInterfaces()[0]
184                 .setProvider(new DefaultProvidedInterface("hallo", Float.class));
185         system.start();
186         RequiredInterface[] required = system.getRequiredInterfaces();
187         assertEquals(1, required.length);
188         ProvidedInterface[] provided = system.getProvidedInterfaces();
189         assertEquals(0, provided.length);
190     }
191
192     public void testCompositeWithExternalDependencesNotProvided() {
193         try {
194             Component environment = new Environment();
195             Component application = new Application();
196             Container system = new Container("all",
197                     new Component[] { application }, new ProvidedInterface[0],
198                     application.getRequiredInterfaces());
199             system.start();
200         } catch (SystemAssemblyException e) {
201             return;
202         }
203         fail();
204
205     }
206
207     public void testDuplicateComponent() {
208         try {
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) {
214             return;
215         }
216         fail();
217     }
218
219     public void testInconsistentHierarchy() {
220         try {
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) {
225             return;
226         }
227         fail();
228     }
229
230     public void testCompositeWithExternalDependencesProvided() {
231
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());
237         environment.start(new DefaultScope(new ProvidedInterface[0]));
238         system.getRequiredInterfaces()[0].setProvider(environment
239                 .getProvidedInterfaces()[0]);
240         system.getRequiredInterfaces()[1].setProvider(environment
241                 .getProvidedInterfaces()[1]);
242
243         system.start();
244         RequiredInterface[] required = system.getRequiredInterfaces();
245         assertEquals(2, required.length);
246         ProvidedInterface[] provided = system.getProvidedInterfaces();
247         assertEquals(0, provided.length);
248
249     }
250
251     public void testAmbiguousInterfaces() {
252         try {
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]);
259             container.start();
260
261         } catch (SystemAssemblyException e) {
262             return;
263         }
264         fail();
265     }
266
267     public void testIncompleteRequirements() {
268         try {
269             Component application = new Application();
270             Container system = new Container("all",
271                     new Component[] { application }, new ProvidedInterface[0],
272                     new RequiredInterface[0]);
273             system.start();
274         } catch (SystemAssemblyException e) {
275             return;
276         }
277         fail();
278     }
279
280     public void testEnvironmentApplicationRollbackOnException()
281             throws Exception {
282         IMocksControl control = EasyMock.createStrictControl();
283
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));
288
289         application.doStart(EasyMockMatchers.anyObject(Scope.class));
290         EasyMock.expectLastCall().andThrow(new RuntimeException());
291         control.replay();
292
293         try {
294             Container container = new Container("root", new Component[] {
295                     environment, application }, new ProvidedInterface[0],
296                     new RequiredInterface[0]);
297
298             container.start();
299         } catch (RuntimeException e) {
300             AssertionUtils.assertEquals(new String[] { "start.environment",
301                     "stop.environment" }, _tracker.getEvents(
302                     Thread.currentThread()).toArray(new String[0]));
303             return;
304         }
305         fail();
306     }
307
308     public void testEnvironmentApplicationRollbackOnExceptionWithExceptionOnStop()
309             throws Exception {
310         IMocksControl control = EasyMock.createControl();
311
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));
317
318         application1.doStop(EasyMock.anyObject());
319         EasyMock.expectLastCall().andThrow(new RuntimeException());
320
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));
326
327         application2.doStart(EasyMockMatchers.anyObject(Scope.class));
328         EasyMock.expectLastCall().andThrow(new RuntimeException());
329
330         control.replay();
331
332         try {
333             Container container = new Container("root", new Component[] {
334                     environment, application1, application2 },
335                     new ProvidedInterface[0], new RequiredInterface[0]);
336
337             container.start();
338         } catch (RuntimeException e) {
339             AssertionUtils.assertEquals(new String[] { "start.environment",
340                     "stop.environment" }, _tracker.getEvents(
341                     Thread.currentThread()).toArray(new String[0]));
342             return;
343         }
344         fail();
345     }
346
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()[0].setProvider(env
354                 .getProvidedInterfaces()[0]);
355         container.getRequiredInterfaces()[1].setProvider(env
356                 .getProvidedInterfaces()[1]);
357         Scope external = new DefaultScope(env.getProvidedInterfaces());
358         env.start(external);
359
360         container.start(external);
361         assertSame(env.getProvidedInterfaces()[0], container
362                 .getRequiredInterfaces()[0].getProvider());
363         assertSame(env.getProvidedInterfaces()[1], container
364                 .getRequiredInterfaces()[1].getProvider());
365         assertSame(env.getProvidedInterfaces()[0], application
366                 .getRequiredInterfaces()[0].getProvider());
367         assertSame(env.getProvidedInterfaces()[1], application
368                 .getRequiredInterfaces()[1].getProvider());
369     }
370
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()[0].setProvider(env
378                 .getProvidedInterfaces()[0]);
379         Scope external = new DefaultScope(new ProvidedInterface[0]);
380         external.publishInterface(env.getProvidedInterfaces()[0], env
381                 .getString());
382         container.start(external);
383         assertSame(env.getProvidedInterfaces()[0], container
384                 .getRequiredInterfaces()[0].getProvider());
385         assertNull(container.getRequiredInterfaces()[1].getProvider());
386         assertSame(env.getProvidedInterfaces()[0], application
387                 .getRequiredInterfaces()[0].getProvider());
388         assertNull(application.getRequiredInterfaces()[1].getProvider());
389     }
390
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()[0].setProvider(env
398                 .getProvidedInterfaces()[0]);
399         container.getRequiredInterfaces()[1].setProvider(env
400                 .getProvidedInterfaces()[1]);
401         try {
402             container.start();
403         } catch (SystemAssemblyException e) {
404             return;
405         }
406         fail();
407     }
408
409     public void testSealed() {
410         final Container container = new Container("xx");
411         assertFalse(container.isSealed());
412         container.start();
413         assertTrue(container.isSealed());
414
415         AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
416             @Override
417             public void run() throws Exception {
418                 container.addComponent(new Application());
419             }
420         }, SystemAssemblyException.class);
421
422         AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
423             @Override
424             public void run() throws Exception {
425                 container.addRestriction(new InterfaceRestriction() {
426                     @Override
427                     public boolean isViolated(Component aClient,
428                             RequiredInterface aRequired, Component aServer,
429                             ProvidedInterface aProvided) {
430                         return false;
431                     }
432                 });
433             }
434         }, SystemAssemblyException.class);
435         AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
436             @Override
437             public void run() throws Exception {
438                 container.addProvidedInterface(new DefaultProvidedInterface(
439                         "xx", String.class));
440             }
441         }, SystemAssemblyException.class);
442
443         AssertionUtils.assertException(new AssertionUtils.ErroneousCode() {
444             @Override
445             public void run() throws Exception {
446                 container.addRequiredInterface(new DefaultRequiredInterface(
447                         "xx", String.class));
448             }
449         }, SystemAssemblyException.class);
450     }
451
452     public void testRestriction() {
453         Environment env1 = new Environment("env1");
454         Environment env2 = new Environment("env2");
455         Application app = new Application("app");
456         Container container = new Container("top").addComponent(env1)
457                 .addComponent(env2).addComponent(app);
458         container.addRestriction(new DefaultInterfaceRestriction("app", null,
459                 "env1", null));
460         container.start();
461         assertEquals(env1.getString(), app.getString());
462         assertFalse(env2.getString().equals(app.getString()));
463     }
464
465     public void testProvidedInDifferentScopes() {
466         // Scoping problem occurred. Externally and internally provided
467         // components clashed
468         // because unique id generation in the scope was wrong.
469
470         StringComponent str = new StringComponent("string");
471         Application app = new Application("app");
472         Container container = new Container("top").addComponent(str)
473                 .addComponent(app);
474         container.addRequiredInterface(new DefaultRequiredInterface("integer",
475                 Integer.class));
476
477         ProvidedInterface provided = new DefaultProvidedInterface("hallo",
478                 Integer.class);
479         container.getRequiredInterfaces()[0].setProvider(provided);
480
481         Scope external = new DefaultScope(new ProvidedInterface[0]);
482         external.publishInterface(provided, 100);
483         Scope scope = container.start(external);
484     }
485
486     public void testProvidedInterfaces() {
487         Environment env = new Environment(_tracker);
488         Container envcontainer = new Container("0").addComponent(env)
489                 .addProvidedInterface(
490                         new DefaultProvidedInterface("string", String.class))
491                 .addProvidedInterface(
492                         new DefaultProvidedInterface("integer", Integer.class));
493         Scope scope = envcontainer.start();
494
495         AssertionUtils.assertEquals(new String[] { "start.environment" },
496                 _tracker.getEvents(Thread.currentThread()).toArray(
497                         new String[0]));
498
499         envcontainer.stop(scope);
500     }
501
502     public void testCoupleTwoContainers() {
503         Environment env = new Environment(_tracker);
504         Container envcontainer = new Container("0").addComponent(env)
505                 .addProvidedInterface(
506                         new DefaultProvidedInterface("string", String.class))
507                 .addProvidedInterface(
508                         new DefaultProvidedInterface("integer", Integer.class));
509
510         Application app = new Application(_tracker);
511         Container appcontainer = new Container("1").addComponent(app)
512                 .addRequiredInterface(
513                         new DefaultRequiredInterface("string", String.class))
514                 .addRequiredInterface(
515                         new DefaultRequiredInterface("integer", Integer.class));
516
517         Container top = new Container("top");
518         top.addComponent(envcontainer).addComponent(appcontainer);
519
520         top.start();
521         AssertionUtils.assertEquals(new String[] { "start.environment",
522                 "start.application" }, _tracker.getEvents(
523                 Thread.currentThread()).toArray(new String[0]));
524
525     }
526 }