    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, 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, false, 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, true, true));
    062            PicoContainer pico = new DefaultPicoContainer();
    063            adapter.getComponentInstance(pico, ComponentAdapter.NOTHING.class);
    064            adapter.dispose(pico);
    065            try {
    066                adapter.start(pico);
    067                fail("IllegalStateException expected");
    068            } catch (Exception e) {
    069                assertEquals("'interface org.picocontainer.testmodel.Touchable' already disposed", e.getMessage());
    070            }
    071        }
    072
    073        @Test public void testComponentCannotBeDisposedIfNotInstantiated() {
    074            Cached adapter = new Cached(
    075                    mockComponentAdapterSupportingLifecycleStrategy(false, false, false, true, false));
    076            PicoContainer pico = new DefaultPicoContainer();
    077            try {
    078                adapter.dispose(pico);
    079             //   fail("IllegalStateException expected");
    080            } catch (Exception e) {
    081                assertEquals("'interface org.picocontainer.testmodel.Touchable' not instantiated", e.getMessage());
    082            }
    083        }
    084
    085        @Test public void testComponentCannotBeStartedIfAlreadyStarted() {
    086            Cached adapter = new Cached(
    087                    mockComponentAdapterSupportingLifecycleStrategy(true, false, false, true, false));
    088            PicoContainer pico = new DefaultPicoContainer();
    089            adapter.start(pico);
    090            try {
    091                adapter.start(pico);
    092                fail("IllegalStateException expected");
    093            } catch (Exception e) {
    094                assertEquals("'interface org.picocontainer.testmodel.Touchable' already started", e.getMessage());
    095            }
    096        }
    097
    098        @Test public void testComponentCannotBeStoppedIfDisposed() {
    099            Cached adapter = new Cached(
    100                    mockComponentAdapterSupportingLifecycleStrategy(false, false, true, true, false));
    101            PicoContainer pico = new DefaultPicoContainer();
    102            adapter.getComponentInstance(pico, ComponentAdapter.NOTHING.class);
    103            adapter.dispose(pico);
    104            try {
    105                adapter.stop(pico);
    106                fail("IllegalStateException expected");
    107            } catch (Exception e) {
    108                assertEquals("'interface org.picocontainer.testmodel.Touchable' already disposed", e.getMessage());
    109            }
    110        }
    111
    112        @Test public void testComponentCannotBeStoppedIfNotInstantiated() {
    113            Cached adapter = new Cached(
    114                    mockComponentAdapterSupportingLifecycleStrategy(false, false, false, true, false));
    115            PicoContainer pico = new DefaultPicoContainer();
    116            try {
    117                adapter.stop(pico);
    118                fail("IllegalStateException expected");
    119            } catch (Exception e) {
    120                assertEquals("'interface org.picocontainer.testmodel.Touchable' not instantiated", e.getMessage());
    121            }
    122        }
    123
    124        @Test public void testComponentCannotBeStoppedIfNotStarted() {
    125            Cached adapter = new Cached(
    126                    mockComponentAdapterSupportingLifecycleStrategy(true, true, false, true, false));
    127            PicoContainer pico = new DefaultPicoContainer();
    128            adapter.start(pico);
    129            adapter.stop(pico);
    130            try {
    131            adapter.stop(pico);
    132                fail("IllegalStateException expected");
    133            } catch (Exception e) {
    134                assertEquals("'interface org.picocontainer.testmodel.Touchable' not started", e.getMessage());
    135            }
    136        }
    137
    138        @Test public void testComponentCannotBeDisposedIfAlreadyDisposed() {
    139            Cached adapter = new Cached(
    140                    mockComponentAdapterSupportingLifecycleStrategy(true, true, true, true, false));
    141            PicoContainer pico = new DefaultPicoContainer();
    142            adapter.start(pico);
    143            adapter.stop(pico);
    144            adapter.dispose(pico);
    145            try {
    146                adapter.dispose(pico);
    147                fail("IllegalStateException expected");
    148            } catch (Exception e) {
    149                assertEquals("'interface org.picocontainer.testmodel.Touchable' already disposed", e.getMessage());
    150            }
    151        }
    152
    153        @Test public void testComponentIsStoppedAndDisposedIfStartedWhenFlushed() {
    154            Cached adapter = new Cached(
    155                    mockComponentAdapterSupportingLifecycleStrategy(true, true, true, false, false));
    156            PicoContainer pico = new DefaultPicoContainer();
    157            adapter.start(pico);
    158            adapter.flush();
    159        }
    160
    161        @Test public void testComponentIsNotStoppedAndDisposedWhenFlushedIfNotStarted() {
    162            Cached adapter = new Cached(
    163                    mockComponentAdapterSupportingLifecycleStrategy(false, false, false, false, false));
    164            adapter.flush();
    165        }
    166
    167        @Test public void testComponentIsNotStoppedAndDisposedWhenFlushedIfDelegateDoesNotSupportLifecycle() {
    168            Cached adapter = new Cached(
    169                    mockComponentAdapterNotSupportingLifecycleStrategy());
    170            adapter.flush();
    171        }
    172
    173        @Test public void testLifecycleIsIgnoredIfDelegateDoesNotSupportIt() {
    174            Cached adapter = new Cached(
    175                    mockComponentAdapterNotSupportingLifecycleStrategy());
    176            PicoContainer pico = new DefaultPicoContainer();
    177            adapter.start(pico);
    178            adapter.stop(pico);
    179            adapter.dispose(pico);
    180        }
    181
    182        @Test public void testCanStopAComponentThatWasNeverStartedBecauseItHasNoLifecycle() {
    183            MutablePicoContainer pico = new DefaultPicoContainer();
    184
    185            pico.addComponent(StringBuffer.class);
    186
    187            pico.start();
    188
    189            assertNotNull(pico.getComponent(StringBuffer.class));
    190
    191            pico.stop();
    192            pico.dispose();
    193        }
    194
    195        private ComponentAdapter mockComponentAdapterNotSupportingLifecycleStrategy() {
    196            return mockery.mock(ComponentAdapter.class);
    197        }
    198
    199        private ComponentAdapter mockComponentAdapterSupportingLifecycleStrategy(
    200                final boolean start, final boolean stop, final boolean dispose, final boolean getKey, final boolean instantiate) {
    201            final boolean hasLifecycle = start || stop || dispose;
    202            final ComponentAdapterSupportingLifecycleStrategy ca = mockery.mock(ComponentAdapterSupportingLifecycleStrategy.class);
    203            mockery.checking(new Expectations(){{
    204                if (getKey) {
    205                    atLeast(1).of(ca).getComponentKey();
    206                    will(returnValue(Touchable.class));
    207                }
    208                if (start) {
    209                    atLeast(1).of(ca).start(with(any(Touchable.class)));
    210                }
    211                if (stop) {
    212                    one(ca).stop(with(any(Touchable.class)));
    213                }
    214                if (dispose) {
    215                    one(ca).dispose(with(any(Touchable.class)));
    216                }
    217                if (hasLifecycle || instantiate) {
    218                    one(ca).getComponentInstance(with(any(PicoContainer.class)), with(same(ComponentAdapter.NOTHING.class)));
    219                    will(returnValue(new SimpleTouchable()));
    220                }
    221                one(ca).getComponentImplementation();
    222                will(returnValue(SimpleTouchable.class));
    223                one(ca).hasLifecycle(with(same(SimpleTouchable.class)));
    224                will(returnValue(true));
    225            }});
    226            return ca;
    227        }
    228
    229        public static interface ComponentAdapterSupportingLifecycleStrategy extends ComponentAdapter,
    230                LifecycleStrategy {
    231        }
    232    }