001    /*****************************************************************************
002     * Copyright (C) PicoContainer Organization. All rights reserved.            *
003     * ------------------------------------------------------------------------- *
004     * The software in this package is published under the terms of the BSD      *
005     * style license a copy of which has been included with this distribution in *
006     * the LICENSE.txt file.                                                     *
007     *****************************************************************************/
008    package org.picocontainer.behaviors;
009    
010    import static org.junit.Assert.assertEquals;
011    import static org.junit.Assert.assertNotNull;
012    import static org.junit.Assert.assertSame;
013    import static org.junit.Assert.fail;
014    import static org.picocontainer.tck.MockFactory.mockeryWithCountingNamingScheme;
015    
016    import org.jmock.Expectations;
017    import org.jmock.Mockery;
018    import org.jmock.integration.junit4.JMock;
019    import org.junit.Test;
020    import org.junit.runner.RunWith;
021    import org.picocontainer.ComponentAdapter;
022    import org.picocontainer.DefaultPicoContainer;
023    import org.picocontainer.LifecycleStrategy;
024    import org.picocontainer.MutablePicoContainer;
025    import org.picocontainer.PicoContainer;
026    import org.picocontainer.testmodel.SimpleTouchable;
027    import org.picocontainer.testmodel.Touchable;
028    
029    
030    
031    /**
032     * @author Mauro Talevi
033     */
034    @RunWith(JMock.class)
035    public class CachedTestCase {
036    
037            private Mockery mockery = mockeryWithCountingNamingScheme();
038            
039        @Test public void testComponentIsNotStartedWhenCachedAndCanBeStarted() {
040            Cached adapter = new Cached(
041                    mockComponentAdapterSupportingLifecycleStrategy(true, false, false));
042            PicoContainer pico = new DefaultPicoContainer();
043            adapter.getComponentInstance(pico, ComponentAdapter.NOTHING.class);
044            adapter.start(pico);
045        }
046    
047        @Test public void testComponentCanBeStartedAgainAfterBeingStopped() {
048            Cached adapter = new Cached(
049                    mockComponentAdapterSupportingLifecycleStrategy(true, true, false));
050            PicoContainer pico = new DefaultPicoContainer();
051            adapter.start(pico);
052            Object instanceAfterFirstStart = adapter.getComponentInstance(pico, ComponentAdapter.NOTHING.class);
053            adapter.stop(pico);
054            adapter.start(pico);
055            Object instanceAfterSecondStart = adapter.getComponentInstance(pico, ComponentAdapter.NOTHING.class);
056            assertSame(instanceAfterFirstStart, instanceAfterSecondStart);
057        }
058    
059        @Test public void testComponentCannotBeStartedIfDisposed() {
060            Cached adapter = new Cached(
061                    mockComponentAdapterSupportingLifecycleStrategy(false, false, true));
062            PicoContainer pico = new DefaultPicoContainer();
063            adapter.dispose(pico);
064            try {
065                adapter.start(pico);
066                fail("IllegalStateException expected");
067            } catch (Exception e) {
068                assertEquals("Already disposed", e.getMessage());
069            }
070        }
071    
072        @Test public void testComponentCannotBeStartedIfAlreadyStarted() {
073            Cached adapter = new Cached(
074                    mockComponentAdapterSupportingLifecycleStrategy(true, false, false));
075            PicoContainer pico = new DefaultPicoContainer();
076            adapter.start(pico);
077            try {
078                adapter.start(pico);
079                fail("IllegalStateException expected");
080            } catch (Exception e) {
081                assertEquals("Already started", e.getMessage());
082            }
083        }
084    
085        @Test public void testComponentCannotBeStoppeddIfDisposed() {
086            Cached adapter = new Cached(
087                    mockComponentAdapterSupportingLifecycleStrategy(false, false, true));
088            PicoContainer pico = new DefaultPicoContainer();
089            adapter.dispose(pico);
090            try {
091                adapter.stop(pico);
092                fail("IllegalStateException expected");
093            } catch (Exception e) {
094                assertEquals("Already disposed", e.getMessage());
095            }
096        }
097    
098        @Test public void testComponentCannotBeStoppedIfNotStarted() {
099            Cached adapter = new Cached(
100                    mockComponentAdapterSupportingLifecycleStrategy(true, true, false));
101            PicoContainer pico = new DefaultPicoContainer();
102            adapter.start(pico);
103            adapter.stop(pico);
104            try {
105            adapter.stop(pico);
106                fail("IllegalStateException expected");
107            } catch (Exception e) {
108                assertEquals("Not started", e.getMessage());
109            }
110        }
111    
112        @Test public void testComponentCannotBeDisposedIfAlreadyDisposed() {
113            Cached adapter = new Cached(
114                    mockComponentAdapterSupportingLifecycleStrategy(true, true, true));
115            PicoContainer pico = new DefaultPicoContainer();
116            adapter.start(pico);
117            adapter.stop(pico);
118            adapter.dispose(pico);
119            try {
120                adapter.dispose(pico);
121                fail("IllegalStateException expected");
122            } catch (Exception e) {
123                assertEquals("Already disposed", e.getMessage());
124            }
125        }
126    
127        @Test public void testComponentIsStoppedAndDisposedIfStartedWhenFlushed() {
128            Cached adapter = new Cached(
129                    mockComponentAdapterSupportingLifecycleStrategy(true, true, true));
130            PicoContainer pico = new DefaultPicoContainer();
131            adapter.start(pico);
132            adapter.flush();
133        }
134    
135        @Test public void testComponentIsNotStoppedAndDisposedWhenFlushedIfNotStarted() {
136            Cached adapter = new Cached(
137                    mockComponentAdapterSupportingLifecycleStrategy(false, false, false));
138            adapter.flush();
139        }
140    
141        @Test public void testComponentIsNotStoppedAndDisposedWhenFlushedIfDelegateDoesNotSupportLifecycle() {
142            Cached adapter = new Cached(
143                    mockComponentAdapterNotSupportingLifecycleStrategy());
144            adapter.flush();
145        }
146    
147        @Test public void testLifecycleIsIgnoredIfDelegateDoesNotSupportIt() {
148            Cached adapter = new Cached(
149                    mockComponentAdapterNotSupportingLifecycleStrategy());
150            PicoContainer pico = new DefaultPicoContainer();
151            adapter.start(pico);
152            adapter.stop(pico);
153            adapter.dispose(pico);
154        }
155    
156        @Test public void testCanStopAComponentThatWasNeverStartedBecauseItHasNoLifecycle() {
157            MutablePicoContainer pico = new DefaultPicoContainer();
158    
159            pico.addComponent(StringBuffer.class);
160    
161            pico.start();
162    
163            assertNotNull(pico.getComponent(StringBuffer.class));
164    
165            pico.stop();
166            pico.dispose();
167        }
168    
169        private ComponentAdapter mockComponentAdapterNotSupportingLifecycleStrategy() {
170            return mockery.mock(ComponentAdapter.class);
171        }
172    
173        private ComponentAdapter mockComponentAdapterSupportingLifecycleStrategy(
174                final boolean start, final boolean stop, final boolean dispose) {
175            final boolean hasLifecycle = start || stop || dispose;
176            final ComponentAdapterSupportingLifecycleStrategy ca = mockery.mock(ComponentAdapterSupportingLifecycleStrategy.class);
177            mockery.checking(new Expectations(){{
178                if (start) {
179                    atLeast(1).of(ca).start(with(any(Touchable.class)));
180                }
181                if (stop) {
182                    one(ca).stop(with(any(Touchable.class)));
183                }
184                if (dispose) {
185                    one(ca).dispose(with(any(Touchable.class)));
186                }
187                if (hasLifecycle) {
188                    one(ca).getComponentInstance(with(any(PicoContainer.class)), with(same(ComponentAdapter.NOTHING.class)));
189                    will(returnValue(new SimpleTouchable()));
190                }
191                one(ca).getComponentImplementation();
192                will(returnValue(SimpleTouchable.class));
193                one(ca).hasLifecycle(with(same(SimpleTouchable.class)));
194                will(returnValue(hasLifecycle));
195            }});
196            return ca;
197        }
198    
199        public static interface ComponentAdapterSupportingLifecycleStrategy extends ComponentAdapter,
200                LifecycleStrategy {
201        }
202    }