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.assertFalse;
011 import org.picocontainer.monitors.NullComponentMonitor;
012 import static org.picocontainer.tck.MockFactory.mockeryWithCountingNamingScheme;
013
014 import java.io.Serializable;
015 import java.lang.reflect.InvocationTargetException;
016 import java.lang.reflect.Member;
017 import java.lang.reflect.Method;
018
019 import org.hamcrest.BaseMatcher;
020 import org.hamcrest.Description;
021 import org.hamcrest.Matcher;
022 import org.jmock.Expectations;
023 import org.jmock.Mockery;
024 import org.jmock.integration.junit4.JMock;
025 import org.junit.Before;
026 import org.junit.Test;
027 import org.junit.runner.RunWith;
028 import org.picocontainer.ComponentAdapter;
029 import org.picocontainer.ComponentMonitor;
030 import org.picocontainer.Disposable;
031 import org.picocontainer.PicoContainer;
032 import org.picocontainer.Startable;
033
034 /**
035 * @author Paul Hammant
036 * @author Mauro Talevi
037 * @author Jörg Schaible
038 */
039 @RunWith(JMock.class)
040 public class ReflectionLifecycleStrategyTestCase {
041
042 private Mockery mockery = mockeryWithCountingNamingScheme();
043
044 private ReflectionLifecycleStrategy strategy;
045 private ComponentMonitor componentMonitor;
046
047 @Before
048 public void setUp() {
049 componentMonitor = mockery.mock(ComponentMonitor.class);
050 strategy = new ReflectionLifecycleStrategy(componentMonitor);
051 }
052
053 @Test
054 public void testStartable() {
055 Object startable = mockComponent(true, false);
056 strategy.start(startable);
057 strategy.stop(startable);
058 strategy.dispose(startable);
059 }
060
061 @Test
062 public void testDisposable() {
063 Object disposable = mockComponent(false, true);
064 strategy.start(disposable);
065 strategy.stop(disposable);
066 strategy.dispose(disposable);
067 }
068
069 @Test
070 public void testNotStartableNorDisposable() {
071 Object serializable = mockery.mock(Serializable.class);
072 assertFalse(strategy.hasLifecycle(serializable.getClass()));
073 strategy.start(serializable);
074 strategy.stop(serializable);
075 strategy.dispose(serializable);
076 }
077
078 @Test
079 public void testStartableBarfingWithError() {
080 try {
081 new ReflectionLifecycleStrategy(new NullComponentMonitor()).start(new Object() {
082 public void start() throws InvocationTargetException {
083 throw new NoClassDefFoundError("foo");
084 }
085 });
086 } catch (Exception e) {
087 System.out.println("");
088 }
089 }
090
091 @Test
092 public void testMonitorChanges() {
093 final ComponentMonitor componentMonitor2 = mockery
094 .mock(ComponentMonitor.class);
095 final Disposable disposable = mockery.mock(Disposable.class);
096 final Matcher<Member> isDisposeMember = new IsMember("dispose");
097 final Matcher<Method> isDisposeMethod = new IsMethod("dispose");
098 mockery.checking(new Expectations() {
099 {
100 atLeast(1).of(disposable).dispose();
101 one(componentMonitor).invoking(
102 with(aNull(PicoContainer.class)),
103 with(aNull(ComponentAdapter.class)),
104 with(isDisposeMember), with(same(disposable)), with(any(Object[].class)));
105 one(componentMonitor).invoked(with(aNull(PicoContainer.class)),
106 with(aNull(ComponentAdapter.class)),
107 with(isDisposeMethod), with(same(disposable)),
108 with(any(Long.class)), with(any(Object[].class)), with(same(null)));
109 one(componentMonitor2).invoking(
110 with(aNull(PicoContainer.class)),
111 with(aNull(ComponentAdapter.class)),
112 with(isDisposeMember), with(same(disposable)), with(any(Object[].class)));
113 one(componentMonitor2).invoked(
114 with(aNull(PicoContainer.class)),
115 with(aNull(ComponentAdapter.class)),
116 with(isDisposeMethod), with(same(disposable)),
117 with(any(Long.class)), with(any(Object[].class)), with(same(null)));
118 }
119 });
120 strategy.dispose(disposable);
121 strategy.changeMonitor(componentMonitor2);
122 strategy.dispose(disposable);
123 }
124
125 @Test
126 public void testWithDifferentTypes() {
127 final MyLifecycle lifecycle = mockery.mock(MyLifecycle.class);
128 final Matcher<Member> isStartMember = new IsMember("start");
129 final Matcher<Method> isStartMethod = new IsMethod("start");
130 final Matcher<Member> isStopMember = new IsMember("stop");
131 final Matcher<Method> isStopMethod = new IsMethod("stop");
132 final Matcher<Member> isDisposeMember = new IsMember("dispose");
133 final Matcher<Method> isDisposeMethod = new IsMethod("dispose");
134 mockery.checking(new Expectations() {
135 {
136 one(lifecycle).start();
137 one(lifecycle).stop();
138 one(lifecycle).dispose();
139 one(componentMonitor).invoking(
140 with(aNull(PicoContainer.class)),
141 with(aNull(ComponentAdapter.class)),
142 with(isStartMember), with(same(lifecycle)), with(any(Object[].class)));
143 one(componentMonitor).invoked(with(aNull(PicoContainer.class)),
144 with(aNull(ComponentAdapter.class)),
145 with(isStartMethod), with(same(lifecycle)),
146 with(any(Long.class)), with(any(Object[].class)), with(same(null)));
147 one(componentMonitor).invoking(
148 with(aNull(PicoContainer.class)),
149 with(aNull(ComponentAdapter.class)),
150 with(isStopMember), with(same(lifecycle)), with(any(Object[].class)));
151 one(componentMonitor).invoked(with(aNull(PicoContainer.class)),
152 with(aNull(ComponentAdapter.class)),
153 with(isStopMethod), with(same(lifecycle)),
154 with(any(Long.class)), with(any(Object[].class)), with(same(null)));
155 one(componentMonitor).invoking(
156 with(aNull(PicoContainer.class)),
157 with(aNull(ComponentAdapter.class)),
158 with(isDisposeMember), with(same(lifecycle)), with(any(Object[].class)));
159 one(componentMonitor).invoked(with(aNull(PicoContainer.class)),
160 with(aNull(ComponentAdapter.class)),
161 with(isDisposeMethod), with(same(lifecycle)),
162 with(any(Long.class)), with(any(Object[].class)), with(same(null)));
163 }
164 });
165
166 Object startable = mockComponent(true, false);
167 strategy.start(startable);
168 strategy.stop(startable);
169 strategy.dispose(startable);
170 startable = lifecycle;
171 strategy.start(startable);
172 strategy.stop(startable);
173 strategy.dispose(startable);
174 }
175
176 private Object mockComponent(boolean startable, boolean disposable) {
177 final Matcher<Member> isStartMember = new IsMember("start");
178 final Matcher<Method> isStartMethod = new IsMethod("start");
179 final Matcher<Member> isStopMember = new IsMember("stop");
180 final Matcher<Method> isStopMethod = new IsMethod("stop");
181 final Matcher<Member> isDisposeMember = new IsMember("dispose");
182 final Matcher<Method> isDisposeMethod = new IsMethod("dispose");
183 if (startable) {
184 final Startable mock = mockery.mock(Startable.class);
185 mockery.checking(new Expectations() {
186 {
187 atLeast(1).of(mock).start();
188 atLeast(1).of(mock).stop();
189 one(componentMonitor).invoking(
190 with(aNull(PicoContainer.class)),
191 with(aNull(ComponentAdapter.class)),
192 with(isStartMember), with(same(mock)), with(any(Object[].class)));
193 one(componentMonitor)
194 .invoked(with(aNull(PicoContainer.class)),
195 with(aNull(ComponentAdapter.class)),
196 with(isStartMethod), with(same(mock)),
197 with(any(Long.class)), with(any(Object[].class)), with(same(null)));
198 one(componentMonitor).invoking(
199 with(aNull(PicoContainer.class)),
200 with(aNull(ComponentAdapter.class)),
201 with(isStopMember), with(same(mock)), with(any(Object[].class)));
202 one(componentMonitor).invoked(
203 with(aNull(PicoContainer.class)),
204 with(aNull(ComponentAdapter.class)),
205 with(isStopMethod), with(same(mock)), with(any(Long.class)), with(any(Object[].class)), with(same(null)));
206 }
207 });
208 return mock;
209 }
210 if (disposable) {
211 final Disposable mock = mockery.mock(Disposable.class);
212 mockery.checking(new Expectations() {
213 {
214 atLeast(1).of(mock).dispose();
215 one(componentMonitor).invoking(
216 with(aNull(PicoContainer.class)),
217 with(aNull(ComponentAdapter.class)),
218 with(isDisposeMember), with(same(mock)), with(any(Object[].class)));
219 one(componentMonitor)
220 .invoked(with(aNull(PicoContainer.class)),
221 with(aNull(ComponentAdapter.class)),
222 with(isDisposeMethod), with(same(mock)),
223 with(any(Long.class)), with(any(Object[].class)), with(same(null)));
224 }
225 });
226 return mock;
227 }
228 return mockery.mock(Serializable.class);
229 }
230
231 public static interface MyLifecycle {
232 void start();
233
234 void stop();
235
236 void dispose();
237 }
238
239 static class IsMember extends BaseMatcher<Member> {
240 private String name;
241
242 public IsMember(String name) {
243 this.name = name;
244 }
245
246 public boolean matches(Object item) {
247 return ((Member) item).getName().equals(name);
248 }
249
250 public void describeTo(Description description) {
251 description.appendText("Should have been a member of name ");
252 description.appendText(name);
253 }
254 };
255
256 static class IsMethod extends BaseMatcher<Method> {
257 private String name;
258
259 public IsMethod(String name) {
260 this.name = name;
261 }
262
263 public boolean matches(Object item) {
264 return ((Method) item).getName().equals(name);
265 }
266
267 public void describeTo(Description description) {
268 description.appendText("Should have been a method of name ");
269 description.appendText(name);
270 }
271 };
272
273 }