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