001    package org.picocontainer.script;
002    
003    import static org.junit.Assert.assertEquals;
004    import static org.junit.Assert.assertNotNull;
005    import static org.junit.Assert.assertNull;
006    import static org.junit.Assert.assertSame;
007    
008    import java.io.ByteArrayInputStream;
009    import java.io.ByteArrayOutputStream;
010    import java.io.IOException;
011    import java.io.ObjectInputStream;
012    import java.io.ObjectOutputStream;
013    import java.io.StringReader;
014    import java.lang.reflect.InvocationTargetException;
015    
016    import org.junit.Test;
017    import org.picocontainer.DefaultPicoContainer;
018    import org.picocontainer.MutablePicoContainer;
019    import org.picocontainer.behaviors.Caching;
020    import org.picocontainer.behaviors.Storing;
021    import org.picocontainer.parameters.ComponentParameter;
022    import org.picocontainer.script.testmodel.FredImpl;
023    import org.picocontainer.script.testmodel.ThingThatTakesParamsInConstructor;
024    import org.picocontainer.script.testmodel.Wilma;
025    import org.picocontainer.script.testmodel.WilmaImpl;
026    import org.picocontainer.script.xml.XMLContainerBuilder;
027    
028    /**
029     * Test case to prove that the DefaultContainerRecorder can be replaced by use of Storing behaviours.
030     * 
031     * @author Konstantin Pribluda
032     * @author Aslak Hellesøy
033     * @author Mauro Talevi
034     */
035    public class StoringContainerTestCase {
036        
037        @Test public void testInvocationsCanBeRecordedAndReplayedOnADifferentContainerInstance() throws Exception {
038    
039            // This test case is not testing Storing. Its just testing that a Caching parent does so.
040            DefaultPicoContainer parent = new DefaultPicoContainer(new Caching());
041            parent.addComponent("fruit", "apple");
042            parent.addComponent("int", 239);
043            parent.addComponent("thing",
044                    ThingThatTakesParamsInConstructor.class,
045                    ComponentParameter.DEFAULT,
046                    ComponentParameter.DEFAULT);
047    
048            Storing storing1 = new Storing();
049            DefaultPicoContainer child1 = new DefaultPicoContainer(storing1, parent);
050            assertEquals("store should be empty", 0, storing1.getCacheSize());
051            Object a1 = child1.getComponent("fruit");
052            assertEquals("store should still be empty: its not used", 0, storing1.getCacheSize());
053            ThingThatTakesParamsInConstructor a2 = (ThingThatTakesParamsInConstructor) child1.getComponent("thing");
054            assertEquals("apple", a1);
055            assertEquals("apple239", a2.getValue());
056    
057            // test that we can replay once more
058            Storing storing2 = new Storing();
059            DefaultPicoContainer child2 = new DefaultPicoContainer(storing2, parent);
060            assertEquals("store should be empty", 0, storing2.getCacheSize());
061            Object b1 = child2.getComponent("fruit");
062            assertEquals("store should still be empty: its not used", 0, storing2.getCacheSize());
063            ThingThatTakesParamsInConstructor b2 = (ThingThatTakesParamsInConstructor) child2.getComponent("thing");
064            assertEquals("apple", b1);
065            assertEquals("apple239", b2.getValue());
066    
067            assertSame("cache of 'recording' parent container should be caching", a1,b1); 
068            assertSame("cache of 'recording' parent container should be caching", a2,b2);
069        }
070    
071        @Test public void testRecorderWorksAfterSerialization() throws IOException, ClassNotFoundException, IllegalAccessException, InvocationTargetException {
072            DefaultPicoContainer recorded = new DefaultPicoContainer(new Caching());
073            recorded.addComponent("fruit", "apple");
074            DefaultPicoContainer replayed = new DefaultPicoContainer(new Storing(), recorded);
075            DefaultPicoContainer serializedReplayed = (DefaultPicoContainer) serializeAndDeserialize(replayed);
076            assertEquals("apple", serializedReplayed.getComponent("fruit"));
077        }
078    
079        private Object serializeAndDeserialize(Object o) throws IOException, ClassNotFoundException {
080            ByteArrayOutputStream baos = new ByteArrayOutputStream();
081            ObjectOutputStream oos = new ObjectOutputStream(baos);
082    
083            oos.writeObject(o);
084            ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
085    
086            return ois.readObject();
087        }
088    
089    
090        @Test public void scriptedPopulationOfContainerHierarchy() {
091    
092            MutablePicoContainer parent = new DefaultPicoContainer(new Caching());
093    
094            // parent has nothing populated in it
095            DefaultPicoContainer child = new DefaultPicoContainer(new Storing(), parent);
096    
097            new XMLContainerBuilder(new StringReader(""
098                    + "<container>"
099                    + "  <component-implementation key='wilma' class='"+WilmaImpl.class.getName()+"'/>"
100                    + "</container>"
101                    ), Thread.currentThread().getContextClassLoader()).populateContainer(child);
102    
103            assertNull(child.getComponent("fred"));
104            assertNotNull(child.getComponent("wilma"));
105    
106            DefaultPicoContainer grandchild = new DefaultPicoContainer(new Storing(), child);
107    
108            new XMLContainerBuilder(new StringReader(
109                      "<container>"
110                    + "  <component-implementation key='fred' class='"+FredImpl.class.getName()+"'>"
111                    + "     <parameter key='wilma'/>"
112                    + "  </component-implementation>"
113                    + "</container>"
114                    ), Thread.currentThread().getContextClassLoader()).populateContainer(grandchild);
115    
116            assertNotNull(grandchild.getComponent("fred"));
117            assertNotNull(grandchild.getComponent("wilma"));
118    
119            FredImpl fred = (FredImpl)grandchild.getComponent("fred");
120            Wilma wilma = (Wilma)grandchild.getComponent("wilma");
121    
122            assertSame(wilma, fred.wilma());
123        }
124    
125    }