KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > picocontainer > defaults > DefaultPicoContainerLifecycleTestCase


1 /*****************************************************************************
2  * Copyright (c) PicoContainer Organization. All rights reserved. *
3  * ------------------------------------------------------------------------- *
4  * The software in this package is published under the terms of the BSD *
5  * style license a copy of which has been included with this distribution in *
6  * the license.html file. *
7  * *
8  * Idea by Rachel Davies, Original code by Aslak Hellesoy and Paul Hammant *
9  *****************************************************************************/

10
11 package org.picocontainer.defaults;
12
13 import junit.framework.Assert;
14 import org.jmock.Mock;
15 import org.jmock.MockObjectTestCase;
16 import org.picocontainer.ComponentMonitor;
17 import org.picocontainer.MutablePicoContainer;
18 import org.picocontainer.PicoContainer;
19 import org.picocontainer.PicoLifecycleException;
20 import org.picocontainer.Startable;
21 import org.picocontainer.monitors.LifecycleComponentMonitor;
22 import org.picocontainer.monitors.LifecycleComponentMonitor.LifecycleFailuresException;
23 import org.picocontainer.testmodel.RecordingLifecycle.FiveTriesToBeMalicious;
24 import org.picocontainer.testmodel.RecordingLifecycle.Four;
25 import org.picocontainer.testmodel.RecordingLifecycle.One;
26 import org.picocontainer.testmodel.RecordingLifecycle.Three;
27 import org.picocontainer.testmodel.RecordingLifecycle.Two;
28
29 import java.lang.reflect.Method JavaDoc;
30 import java.util.ArrayList JavaDoc;
31 import java.util.HashMap JavaDoc;
32 import java.util.List JavaDoc;
33
34 /**
35  * This class tests the lifecycle aspects of DefaultPicoContainer.
36  *
37  * @author Aslak Hellesøy
38  * @author Paul Hammant
39  * @author Ward Cunningham
40  * @version $Revision: 2822 $
41  */

42 public class DefaultPicoContainerLifecycleTestCase extends MockObjectTestCase {
43
44
45     public void testOrderOfInstantiationShouldBeDependencyOrder() throws Exception JavaDoc {
46
47         DefaultPicoContainer pico = new DefaultPicoContainer();
48         pico.registerComponentImplementation("recording", StringBuffer JavaDoc.class);
49         pico.registerComponentImplementation(Four.class);
50         pico.registerComponentImplementation(Two.class);
51         pico.registerComponentImplementation(One.class);
52         pico.registerComponentImplementation(Three.class);
53         final List JavaDoc componentInstances = pico.getComponentInstances();
54
55         // instantiation - would be difficult to do these in the wrong order!!
56
assertEquals("Incorrect Order of Instantiation", One.class, componentInstances.get(1).getClass());
57         assertEquals("Incorrect Order of Instantiation", Two.class, componentInstances.get(2).getClass());
58         assertEquals("Incorrect Order of Instantiation", Three.class, componentInstances.get(3).getClass());
59         assertEquals("Incorrect Order of Instantiation", Four.class, componentInstances.get(4).getClass());
60     }
61
62     public void testOrderOfStartShouldBeDependencyOrderAndStopAndDisposeTheOpposite() throws Exception JavaDoc {
63         DefaultPicoContainer parent = new DefaultPicoContainer();
64         MutablePicoContainer child = parent.makeChildContainer();
65
66         parent.registerComponentImplementation("recording", StringBuffer JavaDoc.class);
67         child.registerComponentImplementation(Four.class);
68         parent.registerComponentImplementation(Two.class);
69         parent.registerComponentImplementation(One.class);
70         child.registerComponentImplementation(Three.class);
71
72         parent.start();
73         parent.stop();
74         parent.dispose();
75
76         assertEquals("<One<Two<Three<FourFour>Three>Two>One>!Four!Three!Two!One",
77                 parent.getComponentInstance("recording").toString());
78     }
79
80
81     public void testLifecycleIsIgnoredIfAdaptersAreNotLifecycleManagers() {
82         DefaultPicoContainer parent = new DefaultPicoContainer(new ConstructorInjectionComponentAdapterFactory());
83         MutablePicoContainer child = parent.makeChildContainer();
84
85         parent.registerComponentImplementation("recording", StringBuffer JavaDoc.class);
86         child.registerComponentImplementation(Four.class);
87         parent.registerComponentImplementation(Two.class);
88         parent.registerComponentImplementation(One.class);
89         child.registerComponentImplementation(Three.class);
90
91         parent.start();
92         parent.stop();
93         parent.dispose();
94
95         assertEquals("",
96                 parent.getComponentInstance("recording").toString());
97     }
98
99     public void testStartStartShouldFail() throws Exception JavaDoc {
100         DefaultPicoContainer pico = new DefaultPicoContainer();
101         pico.start();
102         try {
103             pico.start();
104             fail("Should have failed");
105         } catch (IllegalStateException JavaDoc e) {
106             // expected;
107
}
108     }
109
110     public void testStartStopStopShouldFail() throws Exception JavaDoc {
111         DefaultPicoContainer pico = new DefaultPicoContainer();
112         pico.start();
113         pico.stop();
114         try {
115             pico.stop();
116             fail("Should have failed");
117         } catch (IllegalStateException JavaDoc e) {
118             // expected;
119
}
120     }
121
122     public void testStartStopDisposeDisposeShouldFail() throws Exception JavaDoc {
123         DefaultPicoContainer pico = new DefaultPicoContainer();
124         pico.start();
125         pico.stop();
126         pico.dispose();
127         try {
128             pico.dispose();
129             fail("Should have barfed");
130         } catch (IllegalStateException JavaDoc e) {
131             // expected;
132
}
133     }
134
135     public static class FooRunnable implements Runnable JavaDoc, Startable {
136         private int runCount;
137         private Thread JavaDoc thread = new Thread JavaDoc();
138         private boolean interrupted;
139
140         public FooRunnable() {
141         }
142
143         public int runCount() {
144             return runCount;
145         }
146
147         public boolean isInterrupted() {
148             return interrupted;
149         }
150
151         public void start() {
152             thread = new Thread JavaDoc(this);
153             thread.start();
154         }
155
156         public void stop() {
157             thread.interrupt();
158         }
159
160         // this would do something a bit more concrete
161
// than counting in real life !
162
public void run() {
163             runCount++;
164             try {
165                 Thread.sleep(10000);
166             } catch (InterruptedException JavaDoc e) {
167                 interrupted = true;
168             }
169         }
170     }
171
172     public void testStartStopOfDaemonizedThread() throws Exception JavaDoc {
173         DefaultPicoContainer pico = new DefaultPicoContainer();
174         pico.registerComponentImplementation(FooRunnable.class);
175
176         pico.getComponentInstances();
177         pico.start();
178         Thread.sleep(100);
179         pico.stop();
180
181         FooRunnable foo = (FooRunnable) pico.getComponentInstance(FooRunnable.class);
182         assertEquals(1, foo.runCount());
183         pico.start();
184         Thread.sleep(100);
185         pico.stop();
186         assertEquals(2, foo.runCount());
187     }
188
189     public void testGetComponentInstancesOnParentContainerHostedChildContainerDoesntReturnParentAdapter() {
190         MutablePicoContainer parent = new DefaultPicoContainer();
191         MutablePicoContainer child = parent.makeChildContainer();
192         assertEquals(0, child.getComponentInstances().size());
193     }
194
195     public void testComponentsAreStartedBreadthFirstAndStoppedAndDisposedDepthFirst() {
196         MutablePicoContainer parent = new DefaultPicoContainer();
197         parent.registerComponentImplementation(Two.class);
198         parent.registerComponentImplementation("recording", StringBuffer JavaDoc.class);
199         parent.registerComponentImplementation(One.class);
200         MutablePicoContainer child = parent.makeChildContainer();
201         child.registerComponentImplementation(Three.class);
202         parent.start();
203         parent.stop();
204         parent.dispose();
205
206         assertEquals("<One<Two<ThreeThree>Two>One>!Three!Two!One", parent.getComponentInstance("recording").toString());
207     }
208
209     public void testMaliciousComponentCannotExistInAChildContainerAndSeeAnyElementOfContainerHierarchy() {
210         MutablePicoContainer parent = new DefaultPicoContainer();
211         parent.registerComponentImplementation(Two.class);
212         parent.registerComponentImplementation("recording", StringBuffer JavaDoc.class);
213         parent.registerComponentImplementation(One.class);
214         parent.registerComponentImplementation(Three.class);
215         MutablePicoContainer child = parent.makeChildContainer();
216         child.registerComponentImplementation(FiveTriesToBeMalicious.class);
217         try {
218             parent.start();
219             fail("Thrown " + UnsatisfiableDependenciesException.class.getName() + " expected");
220         } catch ( UnsatisfiableDependenciesException e) {
221             // FiveTriesToBeMalicious can't get instantiated as there is no PicoContainer in any component set
222
}
223         String JavaDoc recording = parent.getComponentInstance("recording").toString();
224         assertEquals("<One<Two<Three", recording);
225         try {
226             child.getComponentInstanceOfType(FiveTriesToBeMalicious.class);
227             fail("Thrown " + UnsatisfiableDependenciesException.class.getName() + " expected");
228         } catch (final UnsatisfiableDependenciesException e) {
229             // can't get instantiated as there is no PicoContainer in any component set
230
}
231         recording = parent.getComponentInstance("recording").toString();
232         assertEquals("<One<Two<Three", recording); // still the same
233
}
234
235
236     public static class NotStartable {
237          public void start(){
238             Assert.fail("start() should not get invoked on NonStartable");
239         }
240     }
241
242     public void testOnlyStartableComponentsAreStartedOnStart() {
243         MutablePicoContainer pico = new DefaultPicoContainer();
244         pico.registerComponentImplementation("recording", StringBuffer JavaDoc.class);
245         pico.registerComponentImplementation(One.class);
246         pico.registerComponentImplementation(NotStartable.class);
247         pico.start();
248         pico.stop();
249         pico.dispose();
250         assertEquals("<OneOne>!One", pico.getComponentInstance("recording").toString());
251     }
252
253     public void testShouldFailOnStartAfterDispose() {
254         MutablePicoContainer pico = new DefaultPicoContainer();
255         pico.dispose();
256         try {
257             pico.start();
258             fail();
259         } catch (IllegalStateException JavaDoc expected) {
260         }
261     }
262
263     public void testShouldFailOnStopAfterDispose() {
264         MutablePicoContainer pico = new DefaultPicoContainer();
265         pico.dispose();
266         try {
267             pico.stop();
268             fail();
269         } catch (IllegalStateException JavaDoc expected) {
270         }
271     }
272
273     public void testShouldStackContainersLast() {
274         // this is merely a code coverage test - but it doesn't seem to cover the StackContainersAtEndComparator
275
// fully. oh well.
276
MutablePicoContainer pico = new DefaultPicoContainer();
277         pico.registerComponentImplementation(ArrayList JavaDoc.class);
278         pico.registerComponentImplementation(DefaultPicoContainer.class);
279         pico.registerComponentImplementation(HashMap JavaDoc.class);
280         pico.start();
281         PicoContainer childContainer = (PicoContainer) pico.getComponentInstance(DefaultPicoContainer.class);
282         // it should be started too
283
try {
284             childContainer.start();
285             fail();
286         } catch (IllegalStateException JavaDoc e) {
287         }
288     }
289
290     public void testCanSpecifyLifeCycleStrategyForInstanceRegistrationWhenSpecifyingComponentAdapterFactory()
291         throws Exception JavaDoc
292     {
293         LifecycleStrategy strategy = new LifecycleStrategy() {
294             public void start(Object JavaDoc component) {
295                 ((StringBuffer JavaDoc)component).append("start>");
296             }
297
298             public void stop(Object JavaDoc component) {
299                 ((StringBuffer JavaDoc)component).append("stop>");
300             }
301
302             public void dispose(Object JavaDoc component) {
303                 ((StringBuffer JavaDoc)component).append("dispose>");
304             }
305
306             public boolean hasLifecycle(Class JavaDoc type) {
307                 return true;
308             }
309         };
310         MutablePicoContainer pico = new DefaultPicoContainer( new DefaultComponentAdapterFactory(), strategy, null );
311
312         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
313
314         pico.registerComponentInstance(sb);
315
316         pico.start();
317         pico.stop();
318         pico.dispose();
319
320         assertEquals("start>stop>dispose>", sb.toString());
321     }
322
323     public void testLifeCycleStrategyForInstanceRegistrationPassedToChildContainers()
324         throws Exception JavaDoc
325     {
326         LifecycleStrategy strategy = new LifecycleStrategy() {
327             public void start(Object JavaDoc component) {
328                 ((StringBuffer JavaDoc)component).append("start>");
329             }
330
331             public void stop(Object JavaDoc component) {
332                 ((StringBuffer JavaDoc)component).append("stop>");
333             }
334
335             public void dispose(Object JavaDoc component) {
336                 ((StringBuffer JavaDoc)component).append("dispose>");
337             }
338
339             public boolean hasLifecycle(Class JavaDoc type) {
340                 return true;
341             }
342         };
343         MutablePicoContainer parent = new DefaultPicoContainer(strategy, null);
344         MutablePicoContainer pico = parent.makeChildContainer();
345
346         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
347
348         pico.registerComponentInstance(sb);
349
350         pico.start();
351         pico.stop();
352         pico.dispose();
353
354         assertEquals("start>stop>dispose>", sb.toString());
355     }
356
357
358     public void testLifecycleDoesNotRecoverWithDefaultComponentMonitor() {
359
360         Mock s1 = mock(Startable.class, "s1");
361         s1.expects(once()).method("start").will(throwException(new RuntimeException JavaDoc("I do not want to start myself")));
362
363         Mock s2 = mock(Startable.class, "s2");
364
365         DefaultPicoContainer dpc = new DefaultPicoContainer();
366         dpc.registerComponentInstance("foo", s1.proxy());
367         dpc.registerComponentInstance("bar", s2.proxy());
368         try {
369             dpc.start();
370             fail("PicoLifecylceException expected");
371         } catch (PicoLifecycleException e) {
372             assertEquals("I do not want to start myself", e.getCause().getMessage());
373         }
374         dpc.stop();
375     }
376
377     public void testLifecycleCanRecoverWithCustomComponentMonitor() throws NoSuchMethodException JavaDoc {
378
379         Mock s1 = mock(Startable.class, "s1");
380         s1.expects(once()).method("start").will(throwException(new RuntimeException JavaDoc("I do not want to start myself")));
381         s1.expects(once()).method("stop");
382
383         Mock s2 = mock(Startable.class, "s2");
384         s2.expects(once()).method("start");
385         s2.expects(once()).method("stop");
386
387         Mock cm = mock(ComponentMonitor.class);
388
389         // s1 expectations
390
cm.expects(once()).method("invoking").with(eq(Startable.class.getMethod("start", (Class JavaDoc[])null)), same(s1.proxy()));
391         cm.expects(once()).method("lifecycleInvocationFailed").with(isA(Method JavaDoc.class),same(s1.proxy()), isA(RuntimeException JavaDoc.class) );
392         cm.expects(once()).method("invoking").with(eq(Startable.class.getMethod("stop", (Class JavaDoc[])null)), same(s1.proxy()));
393         cm.expects(once()).method("invoked").with(eq(Startable.class.getMethod("stop", (Class JavaDoc[])null)), same(s1.proxy()), ANYTHING);
394
395         // s2 expectations
396
cm.expects(once()).method("invoking").with(eq(Startable.class.getMethod("start", (Class JavaDoc[])null)), same(s2.proxy()));
397         cm.expects(once()).method("invoked").with(eq(Startable.class.getMethod("start", (Class JavaDoc[])null)), same(s2.proxy()), ANYTHING);
398         cm.expects(once()).method("invoking").with(eq(Startable.class.getMethod("stop", (Class JavaDoc[])null)), same(s2.proxy()));
399         cm.expects(once()).method("invoked").with(eq(Startable.class.getMethod("stop", (Class JavaDoc[])null)), same(s2.proxy()), ANYTHING);
400
401         DefaultPicoContainer dpc = new DefaultPicoContainer((ComponentMonitor) cm.proxy());
402         dpc.registerComponentInstance("foo", s1.proxy());
403         dpc.registerComponentInstance("bar", s2.proxy());
404         dpc.start();
405         dpc.stop();
406     }
407
408     public void testLifecycleFailuresCanBePickedUpAfterTheEvent() {
409
410         Mock s1 = mock(Startable.class, "s1");
411         s1.expects(once()).method("start").will(throwException(new RuntimeException JavaDoc("I do not want to start myself")));
412         s1.expects(once()).method("stop");
413
414         Mock s2 = mock(Startable.class, "s2");
415         s2.expects(once()).method("start");
416         s2.expects(once()).method("stop");
417
418         LifecycleComponentMonitor lifecycleComponentMonitor = new LifecycleComponentMonitor();
419
420         DefaultPicoContainer dpc = new DefaultPicoContainer(lifecycleComponentMonitor);
421         dpc.registerComponentInstance("foo", s1.proxy());
422         dpc.registerComponentInstance("bar", s2.proxy());
423
424         dpc.start();
425
426         try {
427             lifecycleComponentMonitor.rethrowLifecycleFailuresException();
428             fail("LifecycleFailuresException expected");
429         } catch (LifecycleFailuresException e) {
430             dpc.stop();
431             assertEquals(1, e.getFailures().size());
432         }
433
434     }
435
436     public void testStartedComponentsCanBeStoppedIfSomeComponentsFailToStart() {
437
438         Mock s1 = mock(Startable.class, "s1");
439         s1.expects(once()).method("start");
440         s1.expects(once()).method("stop");
441
442         Mock s2 = mock(Startable.class, "s2");
443         s2.expects(once()).method("start").will(throwException(new RuntimeException JavaDoc("I do not want to start myself")));
444         // s2 does not expect stop().
445

446         DefaultPicoContainer dpc = new DefaultPicoContainer();
447         dpc.registerComponentInstance("foo", s1.proxy());
448         dpc.registerComponentInstance("bar", s2.proxy());
449
450         try {
451             dpc.start();
452             fail("PicoLifecylceException expected");
453         } catch (RuntimeException JavaDoc e) {
454             dpc.stop();
455         }
456
457     }
458
459     public void testStartedComponentsCanBeStoppedIfSomeComponentsFailToStartEvenInAPicoHierarchy() {
460
461         Mock s1 = mock(Startable.class, "s1");
462         s1.expects(once()).method("start");
463         s1.expects(once()).method("stop");
464
465         Mock s2 = mock(Startable.class, "s2");
466         s2.expects(once()).method("start").will(throwException(new RuntimeException JavaDoc("I do not want to start myself")));
467         // s2 does not expect stop().
468

469         DefaultPicoContainer dpc = new DefaultPicoContainer();
470         dpc.registerComponentInstance("foo", s1.proxy());
471         dpc.registerComponentInstance("bar", s2.proxy());
472         dpc.addChildContainer(new DefaultPicoContainer(dpc));
473
474         try {
475             dpc.start();
476             fail("PicoLifecylceException expected");
477         } catch (RuntimeException JavaDoc e) {
478             dpc.stop();
479         }
480
481     }
482
483     public void testChildContainerIsStoppedWhenStartedIndependentlyOfParent() throws Exception JavaDoc {
484
485         DefaultPicoContainer parent = new DefaultPicoContainer();
486
487         parent.start();
488
489         MutablePicoContainer child = parent.makeChildContainer();
490
491         Mock s1 = mock(Startable.class, "s1");
492         s1.expects(once()).method("start");
493         s1.expects(once()).method("stop");
494
495         child.registerComponentInstance(s1.proxy());
496
497         child.start();
498         parent.stop();
499
500     }
501 }
Popular Tags