8b6c61e85fbe873feb02034a55154ed87d2b6efe
[utils] / system / general / src / test / java / org / wamblee / system / core / 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.core;
17
18 import java.io.IOException;
19 import java.io.Serializable;
20 import java.util.Arrays;
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.test.AssertionUtils;
28 import org.wamblee.test.EasyMockMatchers;
29 import org.wamblee.test.EventTracker;
30
31 public class ContainerTest extends TestCase {
32
33         private EventTracker<String> _tracker;
34
35         @Override
36         protected void setUp() throws Exception {
37                 super.setUp();
38                 _tracker = new EventTracker<String>();
39         }
40
41         private static class MyMultiple implements Serializable, Runnable {
42                 @Override
43                 public void run() {
44                         // Empty
45                 }
46         }
47
48         public void testFilterProvided() {
49                 RequiredInterface req1 = new DefaultRequiredInterface("name",
50                                 Runnable.class);
51                 RequiredInterface req2 = new DefaultRequiredInterface("name",
52                                 Serializable.class);
53                 ProvidedInterface prov1 = new DefaultProvidedInterface("name",
54                                 Runnable.class);
55                 ProvidedInterface prov2 = new DefaultProvidedInterface("name",
56                                 Serializable.class);
57                 ProvidedInterface prov3 = new DefaultProvidedInterface("name",
58                                 MyMultiple.class);
59
60                 AssertionUtils.assertEquals(new RequiredInterface[] { req1 }, Container
61                                 .filterRequiredServices(prov1, Arrays
62                                                 .asList(new RequiredInterface[] { req1 })));
63                 AssertionUtils.assertEquals(new RequiredInterface[] { req1 }, Container
64                                 .filterRequiredServices(prov1, Arrays
65                                                 .asList(new RequiredInterface[] { req1, req2 })));
66                 AssertionUtils.assertEquals(new RequiredInterface[] { req1, req2 },
67                                 Container.filterRequiredServices(prov3, Arrays
68                                                 .asList(new RequiredInterface[] { req1, req2 })));
69
70                 AssertionUtils.assertEquals(new ProvidedInterface[] { prov1 },
71                                 Container.filterProvidedServices(req1, Arrays
72                                                 .asList(new ProvidedInterface[] { prov1 })));
73                 AssertionUtils.assertEquals(new ProvidedInterface[] { prov1 },
74                                 Container.filterProvidedServices(req1, Arrays
75                                                 .asList(new ProvidedInterface[] { prov1, prov2 })));
76                 AssertionUtils.assertEquals(new ProvidedInterface[] { prov1, prov3 },
77                                 Container.filterProvidedServices(req1, Arrays
78                                                 .asList(new ProvidedInterface[] { prov1, prov3 })));
79         }
80
81         public void testEnvironmentApplication() {
82                 Environment environment = new Environment(_tracker);
83                 Application application = new Application(_tracker);
84                 Container container = new Container("root", new Component[] {
85                                 environment, application }, new ProvidedInterface[0],
86                                 new RequiredInterface[0]);
87
88                 Scope scope = container.start();
89                 assertTrue(container.isSealed());
90                 AssertionUtils.assertEquals(new String[] { "start.environment",
91                                 "start.application" }, _tracker.getEvents(
92                                 Thread.currentThread()).toArray(new String[0]));
93                 assertEquals(0, scope.getProvidedInterfaces().length);
94                 
95                 assertEquals(environment.getString(), application.getString());
96                 assertEquals(environment.getInteger(), application.getInteger());
97
98         }
99         
100         public void testEnvironmentApplicationSimpleConstructor() {
101                 Environment environment = new Environment(_tracker);
102                 Application application = new Application(_tracker);
103                 Container container = new Container("root").
104                   addComponent(environment).addComponent(application);
105                 
106                 Scope scope = container.start();
107                 AssertionUtils.assertEquals(new String[] { "start.environment",
108                                 "start.application" }, _tracker.getEvents(
109                                 Thread.currentThread()).toArray(new String[0]));
110                 assertEquals(0, scope.getProvidedInterfaces().length);
111                 
112                 assertEquals(environment.getString(), application.getString());
113                 assertEquals(environment.getInteger(), application.getInteger());
114
115         }
116
117         public void testApplicationEnvironment() {
118                 try {
119                         Component environment = new Environment();
120                         Component application = new Application();
121                         Container container = new Container("root", new Component[] {
122                                         application, environment }, new ProvidedInterface[0],
123                                         new RequiredInterface[0]);
124                         container.start();
125                 } catch (SystemAssemblyException e) {
126                         // e.printStackTrace();
127                         return;
128                 }
129                 fail();
130         }
131
132         public void testComposite() {
133                 Component environment = new Environment(_tracker);
134                 Component application = new Application(_tracker);
135                 assertEquals(0, _tracker.getEventCount());
136
137                 Container system = new Container("all", new Component[] { environment,
138                                 application }, new ProvidedInterface[0],
139                                 new RequiredInterface[0]);
140                 Scope runtime = system.start();
141                 RequiredInterface[] required = system.getRequiredInterfaces();
142                 assertEquals(0, required.length);
143                 ProvidedInterface[] provided = system.getProvidedInterfaces();
144                 assertEquals(0, provided.length);
145
146                 AssertionUtils.assertEquals(new String[] { "start.environment",
147                                 "start.application" }, _tracker.getEvents(
148                                 Thread.currentThread()).toArray(new String[0]));
149                 _tracker.clear();
150
151                 system.stop(runtime);
152                 AssertionUtils.assertEquals(new String[] { "stop.application",
153                                 "stop.environment" }, _tracker
154                                 .getEvents(Thread.currentThread()).toArray(new String[0]));
155
156         }
157
158         public void testCompositeWithWrongProvidedInfo() {
159                 try {
160                         Component environment = new Environment();
161                         Component application = new Application();
162                         Container system = new Container("all", new Component[] {
163                                         environment, application },
164                                         new ProvidedInterface[] { new DefaultProvidedInterface(
165                                                         "float", Float.class) },
166                                         new DefaultRequiredInterface[0]);
167                 } catch (SystemAssemblyException e) {
168                         return;
169                 }
170                 fail();
171         }
172
173         public void testCompositeRequiredInterfaceNotProvided() {
174                 try {
175                         Component environment = new Environment();
176                         Component application = new Application();
177                         Container system = new Container("all", new Component[] {
178                                         environment, application }, new ProvidedInterface[0],
179                                         new RequiredInterface[] { new DefaultRequiredInterface(
180                                                         "string", String.class) });
181                         system.start();
182                 } catch (SystemAssemblyException e) {
183                         return;
184                 }
185                 fail();
186         }
187
188         public void testCompositeWithSuperfluousRequiredInfo() {
189                 Component environment = new Environment();
190                 Component application = new Application();
191                 Container system = new Container("all", new Component[] { environment,
192                                 application }, new ProvidedInterface[0],
193                                 new RequiredInterface[] { new DefaultRequiredInterface(
194                                                 "float", Float.class) });
195                 system.getRequiredInterfaces()[0]
196                                 .setProvider(new DefaultProvidedInterface("hallo", Float.class));
197                 system.start();
198                 RequiredInterface[] required = system.getRequiredInterfaces();
199                 assertEquals(1, required.length);
200                 ProvidedInterface[] provided = system.getProvidedInterfaces();
201                 assertEquals(0, provided.length);
202         }
203
204         public void testCompositeWithExternalDependencesNotProvided() {
205                 try {
206                         Component environment = new Environment();
207                         Component application = new Application();
208                         Container system = new Container("all",
209                                         new Component[] { application }, new ProvidedInterface[0],
210                                         application.getRequiredInterfaces());
211                         system.start();
212                 } catch (SystemAssemblyException e) {
213                         return;
214                 }
215                 fail();
216
217         }
218         
219         public void testDuplicateComponent() { 
220             try { 
221                 Component comp1 = new Application(); 
222                 Component comp2 = new Application();
223                 Container system = new Container("top");
224                 system.addComponent(comp1).addComponent(comp2);
225             } catch (SystemAssemblyException e) { 
226                 return; 
227             }
228             fail();
229         }
230         
231
232         public void testInconsistentHierarchy() { 
233             try {
234                 Component comp = new Application(); 
235                 Container system = new Container("top").addComponent(comp);
236                 Container system2 = new Container("top2").addComponent(comp);
237             } catch (SystemAssemblyException e) {
238                 return;
239             }
240             fail();
241         }
242
243         public void testCompositeWithExternalDependencesProvided() {
244
245                 Component environment = new Environment();
246                 Component application = new Application();
247                 Container system = new Container("all",
248                                 new Component[] { application }, new ProvidedInterface[0],
249                                 application.getRequiredInterfaces());
250                 environment.start(new DefaultScope(new ProvidedInterface[0]));
251                 system.getRequiredInterfaces()[0].setProvider(environment
252                                 .getProvidedInterfaces()[0]);
253                 system.getRequiredInterfaces()[1].setProvider(environment
254                                 .getProvidedInterfaces()[1]);
255
256                 system.start();
257                 RequiredInterface[] required = system.getRequiredInterfaces();
258                 assertEquals(2, required.length);
259                 ProvidedInterface[] provided = system.getProvidedInterfaces();
260                 assertEquals(0, provided.length);
261
262         }
263
264         public void testAmbiguousInterfaces() {
265                 try {
266                         Component environment1 = new Environment();
267                         Component environment2 = new Environment();
268                         Component application = new Application();
269                         Container container = new Container("root", new Component[] {
270                                         environment1, environment2, application },
271                                         new ProvidedInterface[0], new RequiredInterface[0]);
272                         container.start();
273
274                 } catch (SystemAssemblyException e) {
275                         return;
276                 }
277                 fail();
278         }
279
280         public void testIncompleteRequirements() {
281                 try {
282                         Component application = new Application();
283                         Container system = new Container("all",
284                                         new Component[] { application }, new ProvidedInterface[0],
285                                         new RequiredInterface[0]);
286                         system.start();
287                 } catch (SystemAssemblyException e) {
288                         return;
289                 }
290                 fail();
291         }
292
293         public void testEnvironmentApplicationRollbackOnException()
294                         throws Exception {
295                 IMocksControl control = EasyMock.createStrictControl();
296
297                 Environment environment = new Environment(_tracker);
298                 Application application = control.createMock(Application.class,
299                                 new ConstructorArgs(Application.class.getConstructor()),
300                                 Application.class.getDeclaredMethod("doStart", Scope.class));
301
302                 application.doStart(EasyMockMatchers.anyObject(Scope.class));
303                 EasyMock.expectLastCall().andThrow(new RuntimeException());
304                 control.replay();
305
306                 try {
307                         Container container = new Container("root", new Component[] {
308                                         environment, application }, new ProvidedInterface[0],
309                                         new RequiredInterface[0]);
310
311                         container.start();
312                 } catch (RuntimeException e) {
313                         AssertionUtils.assertEquals(new String[] { "start.environment",
314                                         "stop.environment" }, _tracker.getEvents(
315                                         Thread.currentThread()).toArray(new String[0]));
316                         return;
317                 }
318                 fail();
319         }
320
321         public void testEnvironmentApplicationRollbackOnExceptionWithExceptionOnStop()
322                         throws Exception {
323                 IMocksControl control = EasyMock.createControl();
324
325                 Environment environment = new Environment(_tracker);
326                 // Application 1 will throw an exception while stopping.
327                 Application application1 = control.createMock(Application.class,
328                                 new ConstructorArgs(Application.class.getConstructor()),
329                                 Application.class.getDeclaredMethod("doStop", Object.class));
330
331                 application1.doStop(EasyMock.anyObject());
332                 EasyMock.expectLastCall().andThrow(new RuntimeException());
333                 
334                 // application 2 will throw an exception while starting
335                 Application application2 = control.createMock(Application.class,
336                                 new ConstructorArgs(Application.class.getConstructor(String.class), "application2"),
337                                 Application.class.getDeclaredMethod("doStart", Scope.class));
338
339                 application2.doStart(EasyMockMatchers.anyObject(Scope.class));
340                 EasyMock.expectLastCall().andThrow(new RuntimeException());
341                 
342                 control.replay();
343
344                 try {
345                         Container container = new Container("root", new Component[] {
346                                         environment, application1, application2 }, new ProvidedInterface[0],
347                                         new RequiredInterface[0]);
348
349                         container.start();
350                 } catch (RuntimeException e) {
351                         AssertionUtils.assertEquals(new String[] { "start.environment", 
352                                         "stop.environment" }, _tracker.getEvents(
353                                         Thread.currentThread()).toArray(new String[0]));
354                         return;
355                 }
356                 fail();
357         }
358         
359         public void testOptionalRequiredInterfaceProvidedOptionalInternal() {
360                 Application application = new Application(true);
361                 Container container = new Container("top", new Component[] { application }, 
362                                 new ProvidedInterface[0], Application.required(true));
363                 Environment env = new Environment();
364                 container.getRequiredInterfaces()[0].setProvider(
365                                 env.getProvidedInterfaces()[0]); 
366                 container.getRequiredInterfaces()[1].setProvider(
367                                 env.getProvidedInterfaces()[1]);
368                 Scope external = new DefaultScope(env.getProvidedInterfaces());
369                 env.start(external); 
370                 
371             container.start(external);
372             assertSame(env.getProvidedInterfaces()[0], container.getRequiredInterfaces()[0].getProvider());
373             assertSame(env.getProvidedInterfaces()[1], container.getRequiredInterfaces()[1].getProvider());
374             assertSame(env.getProvidedInterfaces()[0], application.getRequiredInterfaces()[0].getProvider());
375             assertSame(env.getProvidedInterfaces()[1], application.getRequiredInterfaces()[1].getProvider());
376         }
377         
378         public void testOptionalRequiredInterfaceNotProvidedOptionalInternal() {
379                 Application application = new Application(true);
380                 Container container = new Container("top", new Component[] { application }, 
381                                 new ProvidedInterface[0], Application.required(true));
382                 Environment env = new Environment();
383                 container.getRequiredInterfaces()[0].setProvider(
384                                 env.getProvidedInterfaces()[0]);
385                 Scope external = new DefaultScope(new ProvidedInterface[0]); 
386                 external.publishInterface(env.getProvidedInterfaces()[0], env.getString());
387             container.start(external);
388             assertSame(env.getProvidedInterfaces()[0], container.getRequiredInterfaces()[0].getProvider());
389             assertNull(container.getRequiredInterfaces()[1].getProvider());
390             assertSame(env.getProvidedInterfaces()[0], application.getRequiredInterfaces()[0].getProvider());
391             assertNull(application.getRequiredInterfaces()[1].getProvider());
392         }
393         
394         public void testOptionalRequiredInterfaceProvidedMandatoryInternal() { 
395                 Application application = new Application();
396                 Container container = new Container("top", new Component[] { application }, 
397                                 new ProvidedInterface[0], Application.required(true));
398                 Environment env = new Environment();
399                 container.getRequiredInterfaces()[0].setProvider(
400                                 env.getProvidedInterfaces()[0]); 
401                 container.getRequiredInterfaces()[1].setProvider(
402                                 env.getProvidedInterfaces()[1]);
403             container.start();
404             assertSame(env.getProvidedInterfaces()[0], container.getRequiredInterfaces()[0].getProvider());
405             assertSame(env.getProvidedInterfaces()[1], container.getRequiredInterfaces()[1].getProvider());
406             assertSame(env.getProvidedInterfaces()[0], application.getRequiredInterfaces()[0].getProvider());
407             assertSame(env.getProvidedInterfaces()[1], application.getRequiredInterfaces()[1].getProvider());   
408         }
409         
410         public void testSealed() { 
411                 final Container container = new Container("xx"); 
412                 assertFalse(container.isSealed()); 
413                 container.start();
414                 assertTrue(container.isSealed());
415                 
416                 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { 
417                         @Override
418                         public void run() throws Exception {
419                                 container.addComponent(new Application());      
420                         }
421                 }, SystemAssemblyException.class); 
422                 
423                 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { 
424                         @Override
425                         public void run() throws Exception {
426                                 container.addProvidedInterface(new DefaultProvidedInterface("xx", String.class));       
427                         }
428                 }, SystemAssemblyException.class); 
429                 
430                 AssertionUtils.assertException(new AssertionUtils.ErroneousCode() { 
431                         @Override
432                         public void run() throws Exception {
433                                 container.addRequiredInterface(new DefaultRequiredInterface("xx", String.class));       
434                         }
435                 }, SystemAssemblyException.class); 
436         }
437 }