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 * Idea by Rachel Davies, Original code by Aslak Hellesoy and Paul Hammant *
009 *****************************************************************************/
010
011 package org.picocontainer.alternatives;
012
013 import org.jmock.Mock;
014 import org.jmock.MockObjectTestCase;
015 import org.picocontainer.ComponentAdapter;
016 import org.picocontainer.Disposable;
017 import org.picocontainer.MutablePicoContainer;
018 import org.picocontainer.PicoContainer;
019 import org.picocontainer.PicoVerificationException;
020 import org.picocontainer.PicoVisitor;
021 import org.picocontainer.defaults.DefaultPicoContainer;
022 import org.picocontainer.defaults.VerifyingVisitor;
023
024 import java.util.Collection;
025 import java.util.HashMap;
026 import java.util.Iterator;
027 import java.util.List;
028 import java.util.Map;
029 import java.util.Vector;
030
031 /**
032 * @author Paul Hammant
033 * @version $Revision: 2382 $
034 */
035 public class ImmutablePicoContainerTestCase extends MockObjectTestCase {
036
037 public void testImmutingofNullBarfs() {
038 try {
039 new ImmutablePicoContainer(null);
040 fail("Should have barfed");
041 } catch (NullPointerException e) {
042 //expected
043 }
044 }
045
046 public void testDelegationOfGettingComponentInstance() {
047 DefaultPicoContainer mpc = new DefaultPicoContainer();
048 mpc.registerComponentImplementation(Map.class, HashMap.class);
049 ImmutablePicoContainer ipc = new ImmutablePicoContainer(mpc);
050 Map map = (Map) ipc.getComponentInstance(Map.class);
051 assertNotNull(map);
052 }
053
054 public void testDelegationOfGettingComponentInstanceOfType() {
055 DefaultPicoContainer mpc = new DefaultPicoContainer();
056 mpc.registerComponentImplementation(Map.class, HashMap.class);
057 ImmutablePicoContainer ipc = new ImmutablePicoContainer(mpc);
058 Map map = (Map) ipc.getComponentInstanceOfType(Map.class);
059 assertNotNull(map);
060 }
061
062 public void testDelegationOfGettingComponentInstancesOfType() {
063 DefaultPicoContainer mpc = new DefaultPicoContainer();
064 mpc.registerComponentImplementation(Map.class, HashMap.class);
065 mpc.registerComponentImplementation(Collection.class, Vector.class);
066 ImmutablePicoContainer ipc = new ImmutablePicoContainer(mpc);
067 List list = ipc.getComponentInstancesOfType(Map.class);
068 assertNotNull(list);
069 assertEquals(1,list.size());
070 }
071
072 public void testDelegationOfGetComponentInstances() {
073 DefaultPicoContainer mpc = new DefaultPicoContainer();
074 mpc.registerComponentImplementation(Map.class, HashMap.class);
075 ImmutablePicoContainer ipc = new ImmutablePicoContainer(mpc);
076 List comps = ipc.getComponentInstances();
077 assertNotNull(comps);
078 assertEquals(1, comps.size());
079 }
080
081 public void testDelegationOfGetComponentAdapter() {
082 DefaultPicoContainer mpc = new DefaultPicoContainer();
083 mpc.registerComponentImplementation(Map.class, HashMap.class);
084 ImmutablePicoContainer ipc = new ImmutablePicoContainer(mpc);
085 ComponentAdapter ca = ipc.getComponentAdapter(Map.class);
086 assertNotNull(ca);
087
088 }
089
090 public void testDelegationOfGetComponentAdapterOfType() {
091 DefaultPicoContainer mpc = new DefaultPicoContainer();
092 mpc.registerComponentImplementation(Map.class, HashMap.class);
093 ImmutablePicoContainer ipc = new ImmutablePicoContainer(mpc);
094 ComponentAdapter ca = ipc.getComponentAdapterOfType(Map.class);
095 assertNotNull(ca);
096 }
097
098 public void testDelegationOfGetComponentAdapters() {
099 DefaultPicoContainer mpc = new DefaultPicoContainer();
100 mpc.registerComponentImplementation(Map.class, HashMap.class);
101 ImmutablePicoContainer ipc = new ImmutablePicoContainer(mpc);
102 Collection comps = ipc.getComponentAdapters();
103 assertNotNull(comps);
104 assertEquals(1, comps.size());
105 }
106
107 public void testDelegationOfGetComponentAdaptersOfType() {
108 DefaultPicoContainer mpc = new DefaultPicoContainer();
109 mpc.registerComponentImplementation(Map.class, HashMap.class);
110 ImmutablePicoContainer ipc = new ImmutablePicoContainer(mpc);
111 List comps = ipc.getComponentAdaptersOfType(Map.class);
112 assertNotNull(comps);
113 assertEquals(1, comps.size());
114 }
115
116 public static class UnsatisfiableIterator implements Iterator {
117
118 public UnsatisfiableIterator(Map map) {
119 }
120
121 public void remove() {
122 }
123
124 public boolean hasNext() {
125 return false;
126 }
127
128 public Object next() {
129 return null;
130 }
131 }
132
133 public void testDelegationOfVerify() {
134 DefaultPicoContainer mpc = new DefaultPicoContainer();
135 mpc.registerComponentImplementation(Iterator.class, UnsatisfiableIterator.class);
136 ImmutablePicoContainer ipc = new ImmutablePicoContainer(mpc);
137 try {
138 new VerifyingVisitor().traverse(ipc);
139 fail("PicoVerificationException expected");
140 } catch (PicoVerificationException e) {
141 // expected
142 }
143 try {
144 ipc.verify();
145 fail("PicoVerificationException expected");
146 } catch (PicoVerificationException e) {
147 // expected
148 }
149 }
150
151 public void testGetParentForMutable() {
152 DefaultPicoContainer par = new DefaultPicoContainer();
153 DefaultPicoContainer mpc = new DefaultPicoContainer(par);
154 mpc.registerComponentImplementation(Map.class, HashMap.class);
155 ImmutablePicoContainer ipc = new ImmutablePicoContainer(mpc);
156 PicoContainer parent = ipc.getParent();
157 assertNotNull(parent);
158 assertNotSame(par, parent);
159 PicoContainer parent2 = ipc.getParent();
160 assertNotNull(parent2);
161 assertEquals(parent, parent2);
162 }
163
164 public void testGetParentForNonMutable() {
165 DefaultPicoContainer par = new DefaultPicoContainer();
166 ImmutablePicoContainer par2 = new ImmutablePicoContainer(par);
167 DefaultPicoContainer mpc = new DefaultPicoContainer(par2);
168 mpc.registerComponentImplementation(Map.class, HashMap.class);
169 ImmutablePicoContainer ipc = new ImmutablePicoContainer(mpc);
170 PicoContainer parent = ipc.getParent();
171 assertNotNull(parent);
172 assertNotSame(par, parent);
173 PicoContainer parent2 = ipc.getParent();
174 assertNotNull(parent2);
175 assertEquals(parent, parent2);
176 }
177
178 public void testStartBarfs() {
179 DefaultPicoContainer mpc = new DefaultPicoContainer();
180 mpc.registerComponentImplementation(Map.class, HashMap.class);
181 ImmutablePicoContainer ipc = new ImmutablePicoContainer(mpc);
182 try {
183 ipc.start();
184 fail("should have barfed");
185 } catch (UnsupportedOperationException e) {
186 // expected
187 }
188 }
189
190 public void testStopBarfs() {
191 DefaultPicoContainer mpc = new DefaultPicoContainer();
192 mpc.registerComponentImplementation(Map.class, HashMap.class);
193 ImmutablePicoContainer ipc = new ImmutablePicoContainer(mpc);
194 try {
195 ipc.stop();
196 fail("stop have barfed");
197 } catch (UnsupportedOperationException e) {
198 // expected
199 }
200 }
201
202 public void testDisposeBarfs() {
203 DefaultPicoContainer mpc = new DefaultPicoContainer();
204 mpc.registerComponentImplementation(Map.class, HashMap.class);
205 ImmutablePicoContainer ipc = new ImmutablePicoContainer(mpc);
206 try {
207 ipc.dispose();
208 fail("should have barfed");
209 } catch (UnsupportedOperationException e) {
210 // expected
211 }
212 }
213
214 public static class MyDisposable implements Disposable {
215 public boolean disposed;
216
217 public void dispose() {
218 disposed = true;
219 }
220 }
221
222 public void testLifecycleGuardIsEasyToCircumventSoItMightAsWellBeDeleted() {
223 DefaultPicoContainer mpc = new DefaultPicoContainer();
224 mpc.registerComponentImplementation(MyDisposable.class);
225 ImmutablePicoContainer ipc = new ImmutablePicoContainer(mpc);
226 List componentInstances = ipc.getComponentInstances();
227 for (Iterator iterator = componentInstances.iterator(); iterator.hasNext();) {
228 Object o = iterator.next();
229 if(o instanceof Disposable) {
230 ((Disposable) o).dispose();
231 }
232 }
233 MyDisposable disposable = (MyDisposable ) ipc.getComponentInstance(MyDisposable.class);
234 assertTrue(disposable.disposed);
235 }
236
237 public void testFacetiouslyThatLifeCycleGuardPreventsCyclingOfChildContainersAsComponentsAreNotTheOnlyThingsThatAreLifecycleable() {
238 DefaultPicoContainer parent = new DefaultPicoContainer();
239 MutablePicoContainer child = parent.makeChildContainer();
240 parent.registerComponentImplementation("foo", MyDisposable.class);
241 child.registerComponentImplementation("bar", MyDisposable.class);
242 ImmutablePicoContainer ipc = new ImmutablePicoContainer(parent);
243 try {
244 ipc.dispose();
245 fail("Should have barfed");
246 } catch (UnsupportedOperationException e) {
247 // expected
248 }
249
250 MyDisposable parentDisposable = (MyDisposable) parent.getComponentInstance("foo");
251 assertFalse(parentDisposable.disposed);
252
253 MyDisposable childDisposable = (MyDisposable) child.getComponentInstance("bar");
254 assertFalse(childDisposable.disposed);
255
256 // If this were on parent, it would cascade to child.
257 ((Disposable) ipc.getComponentInstances().get(0)).dispose();
258
259 // I can live with this below....
260 assertTrue(parentDisposable.disposed);
261
262 // However, I'd be in favor of changing
263 // interface PicoContainer extends Startable, Disposable {}
264 // to
265 // interface PicoContainer {}
266 // AND
267 // interface MutablePicoContainer extends PicoContainer {}
268 // to
269 // interface MutablePicoContainer extends PicoContainer implements Startable, Disposable {}
270 // That despite breaking (marginally) backwards compatability.
271 // - Paul
272 }
273
274 public void testVisitingOfImmutableContainerWorks() {
275 DefaultPicoContainer pico = new DefaultPicoContainer();
276 Object foo = new Object();
277 ComponentAdapter componentAdapter = pico.registerComponentInstance(foo);
278
279 Mock fooVisitor = new Mock(PicoVisitor.class);
280 fooVisitor.expects(once()).method("visitContainer").with(eq(pico));
281 fooVisitor.expects(once()).method("visitComponentAdapter").with(eq(componentAdapter));
282
283 ImmutablePicoContainer ipc = new ImmutablePicoContainer(pico);
284
285 ipc.accept((PicoVisitor) fooVisitor.proxy());
286
287
288 }
289 }