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.defaults;
009    
010    import org.jmock.Mock;
011    import org.jmock.MockObjectTestCase;
012    import org.picocontainer.ComponentAdapter;
013    import org.picocontainer.PicoContainer;
014    import org.picocontainer.MutablePicoContainer;
015    import org.picocontainer.testmodel.SimpleTouchable;
016    import org.picocontainer.testmodel.Touchable;
017    
018    
019    /**
020     * @author Mauro Talevi
021     * @version $Revision: $
022     */
023    public class CachingComponentAdapterTestCase extends MockObjectTestCase {
024    
025        public void testComponentIsNotStartedWhenCachedAndCanBeStarted() {
026            CachingComponentAdapter adapter = new CachingComponentAdapter(
027                    mockComponentAdapterSupportingLifecycleStrategy(true, false, false));
028            PicoContainer pico = new DefaultPicoContainer();
029            adapter.getComponentInstance(pico);
030            adapter.start(pico);
031        }
032    
033        public void testComponentCanBeStartedAgainAfterBeingStopped() {
034            CachingComponentAdapter adapter = new CachingComponentAdapter(
035                    mockComponentAdapterSupportingLifecycleStrategy(true, true, false));
036            PicoContainer pico = new DefaultPicoContainer();
037            adapter.start(pico);
038            Object instanceAfterFirstStart = adapter.getComponentInstance(pico);
039            adapter.stop(pico);
040            adapter.start(pico);
041            Object instanceAfterSecondStart = adapter.getComponentInstance(pico);
042            assertSame(instanceAfterFirstStart, instanceAfterSecondStart);
043        }
044    
045        public void testComponentCannotBeStartedIfDisposed() {
046            CachingComponentAdapter adapter = new CachingComponentAdapter(
047                    mockComponentAdapterSupportingLifecycleStrategy(false, false, true));
048            PicoContainer pico = new DefaultPicoContainer();
049            adapter.dispose(pico);
050            try {
051                adapter.start(pico);
052                fail("IllegalStateException expected");
053            } catch (Exception e) {
054                assertEquals("Already disposed", e.getMessage());
055            }
056        }
057    
058        public void testComponentCannotBeStartedIfAlreadyStarted() {
059            CachingComponentAdapter adapter = new CachingComponentAdapter(
060                    mockComponentAdapterSupportingLifecycleStrategy(true, false, false));
061            PicoContainer pico = new DefaultPicoContainer();
062            adapter.start(pico);
063            try {
064                adapter.start(pico);
065                fail("IllegalStateException expected");
066            } catch (Exception e) {
067                assertEquals("Already started", e.getMessage());
068            }
069        }
070    
071        public void testComponentCannotBeStoppeddIfDisposed() {
072            CachingComponentAdapter adapter = new CachingComponentAdapter(
073                    mockComponentAdapterSupportingLifecycleStrategy(false, false, true));
074            PicoContainer pico = new DefaultPicoContainer();
075            adapter.dispose(pico);
076            try {
077                adapter.stop(pico);
078                fail("IllegalStateException expected");
079            } catch (Exception e) {
080                assertEquals("Already disposed", e.getMessage());
081            }
082        }
083    
084        public void testComponentCannotBeStoppedIfNotStarted() {
085            CachingComponentAdapter adapter = new CachingComponentAdapter(
086                    mockComponentAdapterSupportingLifecycleStrategy(true, true, false));
087            PicoContainer pico = new DefaultPicoContainer();
088            adapter.start(pico);
089            adapter.stop(pico);
090            try {
091            adapter.stop(pico);
092                fail("IllegalStateException expected");
093            } catch (Exception e) {
094                assertEquals("Not started", e.getMessage());
095            }
096        }
097    
098        public void testComponentCannotBeDisposedIfAlreadyDisposed() {
099            CachingComponentAdapter adapter = new CachingComponentAdapter(
100                    mockComponentAdapterSupportingLifecycleStrategy(true, true, true));
101            PicoContainer pico = new DefaultPicoContainer();
102            adapter.start(pico);
103            adapter.stop(pico);
104            adapter.dispose(pico);
105            try {
106                adapter.dispose(pico);
107                fail("IllegalStateException expected");
108            } catch (Exception e) {
109                assertEquals("Already disposed", e.getMessage());
110            }
111        }
112    
113        public void testComponentIsStoppedAndDisposedIfStartedWhenFlushed() {
114            CachingComponentAdapter adapter = new CachingComponentAdapter(
115                    mockComponentAdapterSupportingLifecycleStrategy(true, true, true));
116            PicoContainer pico = new DefaultPicoContainer();
117            adapter.start(pico);
118            adapter.flush();
119        }
120    
121        public void testComponentIsNotStoppedAndDisposedWhenFlushedIfNotStarted() {
122            CachingComponentAdapter adapter = new CachingComponentAdapter(
123                    mockComponentAdapterSupportingLifecycleStrategy(false, false, false));
124            adapter.flush();
125        }
126    
127        public void testComponentIsNotStoppedAndDisposedWhenFlushedIfDelegateDoesNotSupportLifecycle() {
128            CachingComponentAdapter adapter = new CachingComponentAdapter(
129                    mockComponentAdapterNotSupportingLifecycleStrategy());
130            adapter.flush();
131        }
132    
133        public void testLifecycleIsIgnoredIfDelegateDoesNotSupportIt() {
134            CachingComponentAdapter adapter = new CachingComponentAdapter(
135                    mockComponentAdapterNotSupportingLifecycleStrategy());
136            PicoContainer pico = new DefaultPicoContainer();
137            adapter.start(pico);
138            adapter.stop(pico);
139            adapter.dispose(pico);
140        }
141    
142        public void testCanStopAComponentThatWasNeverStartedBecauseItHasNoLifecycle() {
143            MutablePicoContainer pico = new DefaultPicoContainer();
144    
145            pico.registerComponentImplementation(StringBuffer.class);
146    
147            pico.start();
148    
149            assertNotNull(pico.getComponentInstance(StringBuffer.class));
150    
151            pico.stop();
152            pico.dispose();
153        }
154    
155        private ComponentAdapter mockComponentAdapterNotSupportingLifecycleStrategy() {
156            Mock mock = mock(ComponentAdapter.class);
157            return (ComponentAdapter)mock.proxy();
158        }
159    
160        private ComponentAdapter mockComponentAdapterSupportingLifecycleStrategy(
161                boolean start, boolean stop, boolean dispose) {
162            boolean hasLifecycle = start || stop || dispose;
163            Mock mock = mock(ComponentAdapterSupportingLifecycleStrategy.class);
164            if (start) {
165                mock.expects(atLeastOnce()).method("start").with(isA(Touchable.class));
166            }
167            if (stop) {
168                mock.expects(once()).method("stop").with(isA(Touchable.class));
169            }
170            if (dispose) {
171                mock.expects(once()).method("dispose").with(isA(Touchable.class));
172            }
173            if (hasLifecycle) {
174                mock.stubs().method("getComponentInstance").with(isA(PicoContainer.class)).will(
175                        returnValue(new SimpleTouchable()));
176            }
177            mock.expects(once()).method("getComponentImplementation").will(
178                    returnValue(SimpleTouchable.class));
179            mock.expects(once()).method("hasLifecycle").with(same(SimpleTouchable.class)).will(
180                    returnValue(hasLifecycle));
181            return (ComponentAdapter)mock.proxy();
182        }
183    
184        static interface ComponentAdapterSupportingLifecycleStrategy extends ComponentAdapter,
185                LifecycleStrategy {
186        }
187    }