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     * Original code by                                                          *
009     *****************************************************************************/
010    package org.picocontainer;
011    
012    import static org.junit.Assert.assertEquals;
013    import static org.junit.Assert.fail;
014    import static org.picocontainer.behaviors.Behaviors.caching;
015    import static org.picocontainer.behaviors.Behaviors.implementationHiding;
016    import static org.picocontainer.behaviors.Behaviors.synchronizing;
017    import static org.picocontainer.injectors.Injectors.SDI;
018    import org.picocontainer.injectors.*;
019    
020    import java.util.ArrayList;
021    import java.util.HashMap;
022    import java.util.HashSet;
023    import java.util.Properties;
024    
025    import org.junit.Before;
026    import org.junit.Test;
027    import org.picocontainer.behaviors.*;
028    import org.picocontainer.containers.EmptyPicoContainer;
029    import org.picocontainer.lifecycle.NullLifecycleStrategy;
030    import org.picocontainer.lifecycle.StartableLifecycleStrategy;
031    import org.picocontainer.lifecycle.ReflectionLifecycleStrategy;
032    import org.picocontainer.monitors.ConsoleComponentMonitor;
033    import org.picocontainer.monitors.NullComponentMonitor;
034    
035    import com.thoughtworks.xstream.XStream;
036    import com.thoughtworks.xstream.converters.Converter;
037    import com.thoughtworks.xstream.converters.MarshallingContext;
038    import com.thoughtworks.xstream.converters.UnmarshallingContext;
039    import com.thoughtworks.xstream.io.HierarchicalStreamReader;
040    import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
041    
042    public class PicoBuilderTestCase {
043    
044        private XStream xs;
045    
046        @Before
047        public void setUp() throws Exception {
048            xs = new XStream();
049            xs.alias("PICO", DefaultPicoContainer.class);
050            xs.registerConverter(new Converter() {
051                public boolean canConvert(Class aClass) {
052                    return aClass.getName().equals("org.picocontainer.DefaultPicoContainer$1") ||
053                           aClass.getName().equals("org.picocontainer.Properties") ||
054                           aClass == Boolean.class ||
055                           aClass == HashSet.class ||
056                           aClass == ArrayList.class;
057                }
058    
059                public void marshal(Object o, HierarchicalStreamWriter hierarchicalStreamWriter, MarshallingContext marshallingContext) {
060                }
061    
062                public Object unmarshal(HierarchicalStreamReader hierarchicalStreamReader, UnmarshallingContext unmarshallingContext) {
063                    return null;
064                }
065            });
066            xs.setMode(XStream.XPATH_ABSOLUTE_REFERENCES);
067        }
068    
069        @Test public void testBasic() {
070            MutablePicoContainer actual = new PicoBuilder().build();
071            MutablePicoContainer expected = new DefaultPicoContainer(new AdaptingInjection(),
072                    new NullLifecycleStrategy(), new EmptyPicoContainer());
073            assertEquals(xs.toXML(expected), xs.toXML(actual));
074        }
075    
076        @Test public void testWithStartableLifecycle() {
077    
078            NullComponentMonitor ncm = new NullComponentMonitor();
079    
080            MutablePicoContainer actual = new PicoBuilder().withLifecycle().build();
081            MutablePicoContainer expected = new DefaultPicoContainer(new AdaptingInjection(),
082                    new StartableLifecycleStrategy(ncm), new EmptyPicoContainer(), ncm);
083            assertEquals(xs.toXML(expected), xs.toXML(actual));
084        }
085    
086        @Test public void testWithReflectionLifecycle() {
087            NullComponentMonitor ncm = new NullComponentMonitor();
088    
089            MutablePicoContainer actual = new PicoBuilder().withReflectionLifecycle().build();
090            MutablePicoContainer expected = new DefaultPicoContainer(new AdaptingInjection(),
091                    new ReflectionLifecycleStrategy(ncm), new EmptyPicoContainer(), ncm);
092            assertEquals(xs.toXML(expected), xs.toXML(actual));
093        }
094    
095    
096        @Test public void testWithConsoleMonitor() {
097            MutablePicoContainer actual = new PicoBuilder().withConsoleMonitor().build();
098            MutablePicoContainer expected = new DefaultPicoContainer(new AdaptingInjection(),
099                    new NullLifecycleStrategy(), new EmptyPicoContainer(), new ConsoleComponentMonitor());
100            assertEquals(xs.toXML(expected), xs.toXML(actual));
101        }
102    
103        @Test public void testWithConsoleMonitorAndLifecycleUseTheSameUltimateMonitor() {
104            MutablePicoContainer actual = new PicoBuilder().withLifecycle().withConsoleMonitor().build();
105            ConsoleComponentMonitor cm = new ConsoleComponentMonitor();
106            MutablePicoContainer expected = new DefaultPicoContainer(new AdaptingInjection(),
107                    new StartableLifecycleStrategy(cm), new EmptyPicoContainer(), cm);
108            assertEquals(xs.toXML(expected), xs.toXML(actual));
109        }
110    
111    
112        @Test public void testWithCustomMonitorByClass() {
113            MutablePicoContainer actual = new PicoBuilder().withMonitor(ConsoleComponentMonitor.class).build();
114            ConsoleComponentMonitor cm = new ConsoleComponentMonitor();
115            MutablePicoContainer expected = new DefaultPicoContainer(new AdaptingInjection(),
116                    new NullLifecycleStrategy(), new EmptyPicoContainer(), cm);
117            assertEquals(xs.toXML(expected), xs.toXML(actual));
118        }
119    
120        @SuppressWarnings({ "unchecked" })
121        @Test public void testWithBogusCustomMonitorByClass() {
122            // We do unchecked assignment so we test what its really doing, and smart IDE's don't complain
123            try {
124                Class aClass = HashMap.class;
125                new PicoBuilder().withMonitor(aClass).build();
126                fail("should have barfed");
127            } catch (ClassCastException e) {
128                // expected
129            }
130        }
131    
132        @Test public void testWithImplementationHiding() {
133            MutablePicoContainer actual = new PicoBuilder().withHiddenImplementations().build();
134            MutablePicoContainer expected = new DefaultPicoContainer(new ImplementationHiding().wrap(new AdaptingInjection()),
135                    new NullLifecycleStrategy(), new EmptyPicoContainer(), new NullComponentMonitor());
136            assertEquals(xs.toXML(expected), xs.toXML(actual));
137        }
138    
139        @Test public void testWithImplementationHidingInstance() {
140            MutablePicoContainer actual = new PicoBuilder().withComponentFactory(new ImplementationHiding()).build();
141            MutablePicoContainer expected = new DefaultPicoContainer(new ImplementationHiding().wrap(new AdaptingInjection()),
142                    new NullLifecycleStrategy(), new EmptyPicoContainer(), new NullComponentMonitor());
143            assertEquals(xs.toXML(expected), xs.toXML(actual));
144        }
145    
146        @Test public void testWithCafsListChainThingy() {
147            MutablePicoContainer actual = new PicoBuilder(SDI()).withBehaviors(caching(), synchronizing(), implementationHiding()).build();
148            MutablePicoContainer expected = new DefaultPicoContainer(new Caching().wrap(new Synchronizing().wrap(new ImplementationHiding().wrap(new SetterInjection()))),
149                    new NullLifecycleStrategy(), new EmptyPicoContainer(), new NullComponentMonitor());
150            assertEquals(xs.toXML(expected), xs.toXML(actual));
151        }
152    
153    
154        public static class CustomParentcontainer extends EmptyPicoContainer {}
155    
156        @Test public void testWithCustomParentContainer() {
157            MutablePicoContainer actual = new PicoBuilder(new CustomParentcontainer()).build();
158            MutablePicoContainer expected = new DefaultPicoContainer(new AdaptingInjection(),
159                    new NullLifecycleStrategy(), new CustomParentcontainer(), new NullComponentMonitor());
160            assertEquals(xs.toXML(expected), xs.toXML(actual));
161        }
162    
163        @Test public void testWithBogusParentContainerBehavesAsIfNotSet() {
164            MutablePicoContainer actual = new PicoBuilder((PicoContainer)null).build();
165            MutablePicoContainer expected = new DefaultPicoContainer(new AdaptingInjection(),
166                    new NullLifecycleStrategy(), new EmptyPicoContainer(), new NullComponentMonitor());
167            assertEquals(xs.toXML(expected), xs.toXML(actual));
168        }
169    
170    
171        @Test public void testWithSetterDI() {
172            MutablePicoContainer actual = new PicoBuilder().withSetterInjection().build();
173            MutablePicoContainer expected = new DefaultPicoContainer(new SetterInjection(),
174                    new NullLifecycleStrategy(), new EmptyPicoContainer(), new NullComponentMonitor());
175            assertEquals(xs.toXML(expected), xs.toXML(actual));
176        }
177    
178        @Test public void testWithAnnotatedMethodDI() {
179                MutablePicoContainer actual = new PicoBuilder().withAnnotatedMethodInjection().build();
180            MutablePicoContainer expected = new DefaultPicoContainer(new AnnotatedMethodInjection(),
181                    new NullLifecycleStrategy(), new EmptyPicoContainer(), new NullComponentMonitor());
182            assertEquals(xs.toXML(expected), xs.toXML(actual));
183        }
184    
185        @Test public void testWithAnnotatedFieldDI() {
186                MutablePicoContainer actual = new PicoBuilder().withAnnotatedFieldInjection().build();
187            MutablePicoContainer expected = new DefaultPicoContainer(new AnnotatedFieldInjection(),
188                    new NullLifecycleStrategy(), new EmptyPicoContainer(), new NullComponentMonitor());
189            assertEquals(xs.toXML(expected), xs.toXML(actual));
190        }
191    
192        @Test public void testWithCtorDI() {
193            MutablePicoContainer actual = new PicoBuilder().withConstructorInjection().build();
194            MutablePicoContainer expected = new DefaultPicoContainer(new ConstructorInjection(),
195                    new NullLifecycleStrategy(), new EmptyPicoContainer(), new NullComponentMonitor());
196            assertEquals(xs.toXML(expected), xs.toXML(actual));
197        }
198    
199        @Test public void testWithImplementationHidingAndSetterDI() {
200            MutablePicoContainer actual = new PicoBuilder().withHiddenImplementations().withSetterInjection().build();
201            MutablePicoContainer expected = new DefaultPicoContainer(new ImplementationHiding().wrap(new SetterInjection()),
202                    new NullLifecycleStrategy(), new EmptyPicoContainer(), new NullComponentMonitor());
203            assertEquals(xs.toXML(expected), xs.toXML(actual));
204        }
205    
206        @Test public void testWithCachingImplementationHidingAndSetterDI() {
207            MutablePicoContainer actual = new PicoBuilder().withCaching().withHiddenImplementations().withSetterInjection().build();
208            MutablePicoContainer expected = new DefaultPicoContainer(new Caching().wrap(new ImplementationHiding().wrap(new SetterInjection())),
209                    new NullLifecycleStrategy(), new EmptyPicoContainer(), new NullComponentMonitor());
210            assertEquals(xs.toXML(expected), xs.toXML(actual));
211        }
212    
213        @Test public void testWithSynchronizing() {
214            MutablePicoContainer actual = new PicoBuilder().withSynchronizing().build();
215            MutablePicoContainer expected = new DefaultPicoContainer(new Synchronizing().wrap(new AdaptingInjection()),
216                    new NullLifecycleStrategy(), new EmptyPicoContainer(), new NullComponentMonitor());
217            assertEquals(xs.toXML(expected), xs.toXML(actual));
218        }
219    
220        @Test public void testWithLocking() {
221            MutablePicoContainer actual = new PicoBuilder().withLocking().build();
222            MutablePicoContainer expected = new DefaultPicoContainer(new Locking().wrap(new AdaptingInjection()),
223                    new NullLifecycleStrategy(), new EmptyPicoContainer(), new NullComponentMonitor());
224            assertEquals(xs.toXML(expected), xs.toXML(actual));
225        }
226    
227        @Test public void testWithPropertyApplier() {
228            MutablePicoContainer actual = new PicoBuilder().withPropertyApplier().build();
229            MutablePicoContainer expected = new DefaultPicoContainer(new PropertyApplying().wrap(new AdaptingInjection()),
230                    new NullLifecycleStrategy(), new EmptyPicoContainer(), new NullComponentMonitor());
231            assertEquals(xs.toXML(expected), xs.toXML(actual));
232        }
233    
234        //TODO - fix up to refer to SomeContainerDependency
235        @Test public void testWithCustomComponentFactory() {
236            MutablePicoContainer actual = new PicoBuilder().withCustomContainerComponent(new SomeContainerDependency()).withComponentFactory(CustomComponentFactory.class).build();
237            MutablePicoContainer expected = new DefaultPicoContainer(new CustomComponentFactory(new SomeContainerDependency()),
238                    new NullLifecycleStrategy(), new EmptyPicoContainer(), new NullComponentMonitor());
239            assertEquals(xs.toXML(expected), xs.toXML(actual));
240        }
241    
242        public static class SomeContainerDependency {
243        }
244        public static class CustomComponentFactory implements ComponentFactory {
245    
246            @SuppressWarnings({ "UnusedDeclaration" })
247            public CustomComponentFactory(SomeContainerDependency someDependency) {
248            }
249    
250            public ComponentAdapter createComponentAdapter(ComponentMonitor componentMonitor,
251                                                           LifecycleStrategy lifecycleStrategy,
252                                                           Properties componentProperties,
253                                                           Object componentKey,
254                                                           Class componentImplementation,
255                                                           Parameter... parameters) throws PicoCompositionException {
256                return null;
257            }
258    
259            public void verify(PicoContainer container) {
260            }
261    
262            public void accept(PicoVisitor visitor) {
263                visitor.visitComponentFactory(this);
264            }
265        }
266    
267    
268        @Test public void testWithCustomPicoContainer() {
269            MutablePicoContainer actual = new PicoBuilder().implementedBy(TestPicoContainer.class).build();
270            MutablePicoContainer expected = new TestPicoContainer(new AdaptingInjection(),
271                    new NullComponentMonitor(), new NullLifecycleStrategy(), new EmptyPicoContainer());
272            assertEquals(xs.toXML(expected), xs.toXML(actual));
273        }
274    
275    
276        public static class TestPicoContainer extends DefaultPicoContainer {
277            public TestPicoContainer(ComponentFactory componentFactory, ComponentMonitor monitor, LifecycleStrategy lifecycleStrategy, PicoContainer parent) {
278                super(componentFactory, lifecycleStrategy, parent, monitor);
279            }
280        }
281    
282    
283    }