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 }