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.behaviors;
011
012 import static org.junit.Assert.assertEquals;
013 import static org.junit.Assert.assertFalse;
014 import static org.junit.Assert.assertNotNull;
015 import static org.junit.Assert.assertNotSame;
016 import static org.junit.Assert.assertSame;
017 import static org.junit.Assert.fail;
018
019 import org.junit.Test;
020 import org.picocontainer.DefaultPicoContainer;
021
022 public class StoringTestCase {
023
024 public static class Foo {
025 public Foo(StringBuilder sb) {
026 sb.append("<Foo");
027 }
028 }
029
030 public static class Bar {
031 private final Foo foo;
032 public Bar(StringBuilder sb, Foo foo) {
033 this.foo = foo;
034 sb.append("<Bar");
035 }
036 }
037
038 @Test public void testThatForASingleThreadTheBehaviorIsTheSameAsPlainCaching() {
039
040 DefaultPicoContainer parent = new DefaultPicoContainer(new Caching());
041 Storing storeCaching = new Storing();
042 DefaultPicoContainer child = new DefaultPicoContainer(storeCaching, parent);
043
044 parent.addComponent(StringBuilder.class);
045 child.addComponent(Foo.class);
046
047 StringBuilder sb = parent.getComponent(StringBuilder.class);
048 Foo foo = child.getComponent(Foo.class);
049 Foo foo2 = child.getComponent(Foo.class);
050 assertNotNull(foo);
051 assertNotNull(foo2);
052 assertEquals(foo,foo2);
053 assertEquals("<Foo", sb.toString());
054 assertEquals("Stored:ConstructorInjector-class org.picocontainer.behaviors.StoringTestCase$Foo", child.getComponentAdapter(Foo.class).toString());
055 }
056
057 @Test public void testThatTwoThreadsHaveSeparatedCacheValues() {
058
059 final Foo[] foos = new Foo[4];
060
061 DefaultPicoContainer parent = new DefaultPicoContainer(new Caching());
062 final DefaultPicoContainer child = new DefaultPicoContainer(new Storing(), parent);
063
064 parent.addComponent(StringBuilder.class);
065 child.addComponent(Foo.class);
066
067 StringBuilder sb = parent.getComponent(StringBuilder.class);
068 foos[0] = child.getComponent(Foo.class);
069
070 Thread thread = new Thread() {
071 public void run() {
072 foos[1] = child.getComponent(Foo.class);
073 foos[3] = child.getComponent(Foo.class);
074 }
075 };
076 thread.start();
077 foos[2] = child.getComponent(Foo.class);
078 sleepALittle();
079
080 assertNotNull(foos[0]);
081 assertNotNull(foos[1]);
082 assertNotNull(foos[2]);
083 assertNotNull(foos[3]);
084 assertSame(foos[0],foos[2]);
085 assertEquals(foos[1],foos[3]);
086 assertFalse(foos[0] == foos[1]);
087 assertEquals("<Foo<Foo", sb.toString());
088 assertEquals("Stored:ConstructorInjector-class org.picocontainer.behaviors.StoringTestCase$Foo", child.getComponentAdapter(Foo.class).toString());
089 }
090
091 @Test public void testThatTwoThreadsHaveSeparatedCacheValuesForThreeScopeScenario() {
092
093 final Foo[] foos = new Foo[4];
094 final Bar[] bars = new Bar[4];
095
096 DefaultPicoContainer appScope = new DefaultPicoContainer(new Caching());
097 final DefaultPicoContainer sessionScope = new DefaultPicoContainer(new Storing(), appScope);
098 final DefaultPicoContainer requestScope = new DefaultPicoContainer(new Storing(), sessionScope);
099
100 appScope.addComponent(StringBuilder.class);
101 sessionScope.addComponent(Foo.class);
102 requestScope.addComponent(Bar.class);
103
104 StringBuilder sb = appScope.getComponent(StringBuilder.class);
105 foos[0] = sessionScope.getComponent(Foo.class);
106 bars[0] = requestScope.getComponent(Bar.class);
107
108 Thread thread = new Thread() {
109 public void run() {
110 foos[1] = sessionScope.getComponent(Foo.class);
111 bars[1] = requestScope.getComponent(Bar.class);
112 foos[3] = sessionScope.getComponent(Foo.class);
113 bars[3] = requestScope.getComponent(Bar.class);
114 }
115 };
116 thread.start();
117 foos[2] = sessionScope.getComponent(Foo.class);
118 bars[2] = requestScope.getComponent(Bar.class);
119 sleepALittle();
120
121 assertSame(bars[0],bars[2]);
122 assertEquals(bars[1],bars[3]);
123 assertFalse(bars[0] == bars[1]);
124 assertSame(bars[0].foo,foos[0]);
125 assertSame(bars[1].foo,foos[1]);
126 assertSame(bars[2].foo,foos[2]);
127 assertSame(bars[3].foo,foos[3]);
128 assertEquals("<Foo<Bar<Foo<Bar", sb.toString());
129 assertEquals("Stored:ConstructorInjector-class org.picocontainer.behaviors.StoringTestCase$Foo", sessionScope.getComponentAdapter(Foo.class).toString());
130 }
131
132 @Test public void testThatCacheMapCanBeReUsedOnASubsequentThreadSimulatingASessionConcept() {
133
134 final Foo[] foos = new Foo[4];
135
136 DefaultPicoContainer parent = new DefaultPicoContainer(new Caching());
137 final Storing storeCaching = new Storing();
138 final DefaultPicoContainer child = new DefaultPicoContainer(storeCaching, parent);
139
140 parent.addComponent(StringBuilder.class);
141 child.addComponent(Foo.class);
142
143 StringBuilder sb = parent.getComponent(StringBuilder.class);
144
145 final Storing.StoreWrapper[] tmpMap = new Storing.StoreWrapper[1];
146 Thread thread = new Thread() {
147 public void run() {
148 foos[0] = child.getComponent(Foo.class);
149 foos[1] = child.getComponent(Foo.class);
150 tmpMap[0] = storeCaching.getCacheForThread();
151
152 }
153 };
154 thread.start();
155 sleepALittle();
156 thread = new Thread() {
157 public void run() {
158 storeCaching.putCacheForThread(tmpMap[0]);
159 foos[2] = child.getComponent(Foo.class);
160 foos[3] = child.getComponent(Foo.class);
161 tmpMap[0] = storeCaching.getCacheForThread();
162
163 }
164 };
165 thread.start();
166 sleepALittle();
167
168 assertNotNull(foos[0]);
169 assertNotNull(foos[1]);
170 assertNotNull(foos[2]);
171 assertNotNull(foos[3]);
172 assertSame(foos[0],foos[1]);
173 assertSame(foos[1],foos[2]);
174 assertSame(foos[2],foos[3]);
175 assertEquals("<Foo", sb.toString());
176 assertEquals("Stored:ConstructorInjector-class org.picocontainer.behaviors.StoringTestCase$Foo", child.getComponentAdapter(Foo.class).toString());
177 }
178
179 @Test public void testThatCacheMapCanBeResetOnASubsequentThreadSimulatingASessionConcept() {
180
181
182 DefaultPicoContainer parent = new DefaultPicoContainer(new Caching());
183 final Storing storeCaching = new Storing();
184 final DefaultPicoContainer child = new DefaultPicoContainer(storeCaching, parent);
185
186 parent.addComponent(StringBuilder.class);
187 child.addComponent(Foo.class);
188
189 StringBuilder sb = parent.getComponent(StringBuilder.class);
190
191 Foo one = child.getComponent(Foo.class);
192 Foo two = child.getComponent(Foo.class);
193
194 assertNotNull(one);
195 assertNotNull(two);
196 assertSame(one,two);
197
198 storeCaching.resetCacheForThread();
199
200 Foo three = child.getComponent(Foo.class);
201 Foo four = child.getComponent(Foo.class);
202
203 assertNotNull(three);
204 assertNotNull(four);
205 assertNotSame(one,three);
206 assertSame(three,four);
207
208 assertEquals("<Foo<Foo", sb.toString());
209 assertEquals("Stored:ConstructorInjector-class org.picocontainer.behaviors.StoringTestCase$Foo", child.getComponentAdapter(Foo.class).toString());
210 }
211
212 @Test public void testThatCacheMapCanBeDisabledSimulatingAnEndedRequest() {
213
214 DefaultPicoContainer parent = new DefaultPicoContainer(new Caching());
215 final Storing storeCaching = new Storing();
216 final DefaultPicoContainer child = new DefaultPicoContainer(storeCaching, parent);
217
218 parent.addComponent(StringBuilder.class);
219 child.addComponent(Foo.class);
220
221 StringBuilder sb = parent.getComponent(StringBuilder.class);
222
223 Foo one = child.getComponent(Foo.class);
224 Foo two = child.getComponent(Foo.class);
225
226 assertNotNull(one);
227 assertNotNull(two);
228 assertSame(one,two);
229
230 storeCaching.invalidateCacheForThread();
231
232 try {
233 Foo three = child.getComponent(Foo.class);
234 fail("should have barfed");
235 } catch (UnsupportedOperationException e) {
236 // expected
237 }
238 }
239
240
241 private void sleepALittle() {
242 try {
243 Thread.sleep(100);
244 } catch (InterruptedException e) {
245 }
246 }
247
248
249 }