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 }