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.lifecycle;
009    
010    import static org.junit.Assert.assertEquals;
011    import static org.junit.Assert.assertTrue;
012    import static org.junit.Assert.fail;
013    import static org.picocontainer.Characteristics.CACHE;
014    import static org.picocontainer.tck.MockFactory.mockeryWithCountingNamingScheme;
015    
016    import java.io.Serializable;
017    
018    import org.jmock.Expectations;
019    import org.jmock.Mockery;
020    import org.jmock.integration.junit4.JMock;
021    import org.junit.Before;
022    import org.junit.Test;
023    import org.junit.runner.RunWith;
024    import org.picocontainer.DefaultPicoContainer;
025    import org.picocontainer.Disposable;
026    import org.picocontainer.PicoLifecycleException;
027    import org.picocontainer.Startable;
028    import org.picocontainer.containers.EmptyPicoContainer;
029    import org.picocontainer.monitors.NullComponentMonitor;
030    
031    /**
032     * 
033     * @author Mauro Talevi
034     */
035    @SuppressWarnings("serial")
036    @RunWith(JMock.class)
037    public class StartableLifecycleStrategyTestCase {
038    
039            private Mockery mockery = mockeryWithCountingNamingScheme();
040            
041        private StartableLifecycleStrategy strategy;
042        
043        @Before
044        public void setUp(){
045            strategy = new StartableLifecycleStrategy(new NullComponentMonitor());
046        }
047    
048        @Test public void testStartable(){
049            Object startable = mockComponent(true, false);
050            strategy.start(startable);
051            strategy.stop(startable);
052        }
053    
054        @Test public void testDisposable(){
055            Object startable = mockComponent(false, true);
056            strategy.dispose(startable);
057        }
058    
059        @Test public void testSerializable(){
060            Object serializable = mockComponent(false, false);
061            strategy.start(serializable);
062            strategy.stop(serializable);
063            strategy.dispose(serializable);
064        }
065        
066        private Object mockComponent(boolean startable, boolean disposeable) {
067            if ( startable ) {
068                     final Startable mock = mockery.mock(Startable.class);
069                     mockery.checking(new Expectations() {{
070                     one(mock).start(); 
071                     one(mock).stop(); 
072                 }});
073                     return mock;
074            }
075            if ( disposeable ) {
076             final Disposable mock = mockery.mock(Disposable.class);
077             mockery.checking(new Expectations() {{
078                 one(mock).dispose(); 
079             }});
080             return mock;
081            }
082            return mockery.mock(Serializable.class);
083        }
084    
085        interface ThirdPartyStartable {
086            void sstart() throws Exception;
087            void sstop();
088            void ddispose();
089        }
090        public static class ThirdPartyStartableComponent implements ThirdPartyStartable {
091            StringBuilder sb;
092            public ThirdPartyStartableComponent(StringBuilder sb) {
093                this.sb = sb;
094            }
095    
096            public void sstart() {
097                sb.append("<");
098            }
099    
100            public void sstop() {
101                sb.append(">");
102            }
103    
104            public void ddispose() {
105                sb.append("!");
106            }
107        }
108    
109        public static class ThirdPartyStartableComponent2 implements ThirdPartyStartable {
110            public void sstart() {
111                throw new UnsupportedOperationException();
112            }
113            public void sstop() {
114            }
115    
116            public void ddispose() {
117            }
118        }
119    
120        public static class ThirdPartyStartableComponent3 implements ThirdPartyStartable {
121            public void sstart() throws Exception {
122                throw new Exception("whoaa!");
123            }
124            public void sstop() {
125            }
126    
127            public void ddispose() {
128            }
129        }
130    
131        @Test public void testThirdPartyStartableAndDisposable() {
132            DefaultPicoContainer pico = new DefaultPicoContainer(new MyStartableLifecycleStrategy(), new EmptyPicoContainer());
133            StringBuilder sb = new StringBuilder();
134            pico.addComponent(sb);
135            pico.as(CACHE).addComponent(ThirdPartyStartableComponent.class);
136            pico.start();
137            pico.stop();
138            pico.dispose();
139            assertEquals("<>!", sb.toString());
140    
141        }
142    
143        @Test public void testThirdPartyStartableCanNoteLifecycleRuntimeException() {
144            DefaultPicoContainer pico = new DefaultPicoContainer(new MyStartableLifecycleStrategy(), new EmptyPicoContainer());
145            pico.as(CACHE).addComponent(ThirdPartyStartableComponent2.class);
146            try {
147                pico.start();
148                fail("should have barfed");
149            } catch (PicoLifecycleException e) {
150                assertTrue(e.getCause() instanceof UnsupportedOperationException);
151                assertTrue(e.getInstance() instanceof ThirdPartyStartableComponent2);
152                assertEquals("sstart", e.getMethod().getName());
153                // expected
154            }
155    
156        }
157    
158        @Test public void testThirdPartyStartableCanNoteLifecycleException() {
159            DefaultPicoContainer pico = new DefaultPicoContainer(new MyStartableLifecycleStrategy(), new EmptyPicoContainer());
160            pico.as(CACHE).addComponent(ThirdPartyStartableComponent3.class);
161            try {
162                pico.start();
163                fail("should have barfed");
164            } catch (PicoLifecycleException e) {
165                Throwable throwable = e.getCause();
166                assertTrue(throwable instanceof Exception);
167                String s = throwable.getMessage();
168                assertEquals("whoaa!", s);
169                assertTrue(e.getInstance() instanceof ThirdPartyStartableComponent3);
170                assertEquals("sstart", e.getMethod().getName());
171                // expected
172            }
173    
174        }
175    
176        private static class MyStartableLifecycleStrategy extends StartableLifecycleStrategy {
177            public MyStartableLifecycleStrategy() {
178                super(new NullComponentMonitor());
179            }
180    
181            protected String getStopMethodName() {
182                return "sstop";
183            }
184    
185            protected String getStartMethodName() {
186                return "sstart";
187            }
188    
189            protected String getDisposeMethodName() {
190                return "ddispose";
191            }
192    
193    
194            protected Class getStartableInterface() {
195                return ThirdPartyStartable.class;
196            }
197    
198            protected Class getDisposableInterface() {
199                return ThirdPartyStartable.class;
200            }
201        }
202    }