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