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 }