1   /* Copyright (c) 2004-2005, University Health Network.  All rights reserved. Distributed under the BSD 
2    * license (see http://opensource.org/licenses/bsd-license.php).
3    */
4   
5   package ca.uhn.cache.internal.impl;
6   
7   import java.util.ArrayList;
8   import java.util.Collection;
9   import java.util.Iterator;
10  
11  import junit.framework.TestCase;
12  import junitx.framework.ArrayAssert;
13  
14  import org.springframework.beans.factory.BeanFactory;
15  import org.springframework.context.support.ClassPathXmlApplicationContext;
16  
17  import ca.uhn.cache.CacheReasonEnum;
18  import ca.uhn.cache.IQuery;
19  import ca.uhn.cache.VolatilityEnum;
20  import ca.uhn.cache.impl.Dimension;
21  import ca.uhn.cache.impl.Query;
22  import ca.uhn.cache.impl.StringSetParam;
23  import ca.uhn.cache.internal.IChunk;
24  import ca.uhn.cache.util.SpringTestCaseUtils;
25  
26  
27  /***
28   * Tests for chunk store.
29   *
30   * @author <a href="mailto:alexei.guevara@uhn.on.ca">Alexei Guevara</a>
31   * @version $Revision: 1.1 $ updated on $Date: 2005/01/24 22:52:21 $ by $Author: bryan_tripp $
32   */
33  public class HibernateChunkStoreTest extends TestCase {
34  
35      //enable assertions
36      static {
37          ClassLoader.getSystemClassLoader().setPackageAssertionStatus( "ca.uhn.cache", true );
38      }
39      
40      private HibernateChunkStore myHibernateChunkStore;
41      
42      private IChunk myChunk1;
43      private IChunk myChunk2;
44      
45      private IQuery myChunk1Query;    
46      private IQuery myChunk2Query;
47  
48      private BeanFactory myBeanFactory;
49      
50      private Collection myTrackedChunks;
51      /*
52       * @see TestCase#setUp()
53       */
54      protected void setUp() throws Exception {
55          super.setUp();
56          
57          myBeanFactory = 
58              new ClassPathXmlApplicationContext( 
59                      SpringTestCaseUtils.packageToPath( HibernateChunkStoreTest.class.getPackage() ) +
60                      "/hibernate-chunk-store.xml");
61          
62          
63          myHibernateChunkStore = ( HibernateChunkStore ) myBeanFactory.getBean( "myChunkStore" );
64          
65          myTrackedChunks = new ArrayList( );
66          
67          Dimension dimension1 = new Dimension( "P( A, B, C, D, E )", new Class[] { StringSetParam.class } );
68          
69          StringSetParam chunk1QueryParam1 = new StringSetParam( dimension1, new String[] { "A", "B" } );
70  
71          myChunk1Query = new Query();
72          myChunk1Query.addParameter( chunk1QueryParam1 );
73          
74          StringSetParam chunk2QueryParam1 = new StringSetParam( dimension1, new String[] { "C", "D", "E" } );
75          myChunk2Query = new Query();
76          myChunk2Query.addParameter( chunk2QueryParam1 );
77      }
78  
79      /*
80       * @see TestCase#tearDown()
81       */
82      protected void tearDown() throws Exception {
83          super.tearDown();
84  
85          Iterator iter = myTrackedChunks.iterator( );
86          
87          while(iter.hasNext()) {
88              IQuery key = (IQuery)iter.next();
89              myHibernateChunkStore.remove(key);
90          }
91          
92          myTrackedChunks = null;
93          
94          myHibernateChunkStore = null;
95      }
96  
97      /***
98       * @throws Exception on any unexpected exception ...
99       */
100     public void testGetPreconditions() throws Exception {
101         
102         IQuery query = null;
103 
104         try{
105             myHibernateChunkStore.get(query);
106             fail("AssertionError must be thrown");
107         }
108         catch(AssertionError e){
109         }
110 
111         query = new Query();
112         
113         try{
114             myHibernateChunkStore.get(query);
115             fail("AssertionError must be thrown");
116         }
117         catch(AssertionError e){
118         }
119 
120     }
121 
122 
123     /***
124      * @throws Exception on any unexpected exception ...
125      */
126     public void testPutPreconditions() throws Exception {
127 
128         IQuery query = null;
129 
130         try{
131             myHibernateChunkStore.put(query, null, null);
132             fail("AssertionError must be thrown");
133         }
134         catch(AssertionError e){
135         }
136 
137         query = new Query();
138         
139         try{
140             myHibernateChunkStore.put(query, null, null);
141             fail("AssertionError must be thrown");
142         }
143         catch(AssertionError e){
144         }
145 
146         try{
147             myHibernateChunkStore.put(myChunk1Query, null, null);
148             fail("AssertionError must be thrown");
149         }
150         catch(AssertionError e){
151         }
152 
153         try{
154             myHibernateChunkStore.put(myChunk1Query, VolatilityEnum.STABLE, null);
155             fail("AssertionError must be thrown");
156         }
157         catch(AssertionError e){
158         }
159 
160         try{
161             myHibernateChunkStore.put(query, VolatilityEnum.STABLE, new CacheReasonEnum[0]);
162             fail("AssertionError must be thrown");
163         }
164         catch(AssertionError e){
165         }
166             
167         try{
168             trackChunk(myChunk1Query);
169             myHibernateChunkStore.put(myChunk1Query, VolatilityEnum.STABLE, 
170                                       new CacheReasonEnum[] { CacheReasonEnum.PRE_FETCH });
171         }
172         catch(AssertionError e){
173             fail("AssertionError must not be thrown");
174         }
175     }
176     
177     /***
178      * @throws Exception on any unexpected exception ...
179      */
180     public void testRemovePreconditions() throws Exception {
181 
182         IQuery query = null;
183 
184         try{
185             myHibernateChunkStore.remove(query);
186             fail("AssertionError must be thrown");
187         }
188         catch(AssertionError e){
189         }
190 
191         query = new Query();
192 
193         try{
194             myHibernateChunkStore.remove(query);
195             fail("AssertionError must be thrown");
196         }
197         catch(AssertionError e){
198         }
199         
200     }
201     
202 
203     /***
204      * - start with empty chunk store
205      * - put a query in there, then retrieve it.
206      * - make sure the volatility, reasons and query are correct
207      * - remove it
208      * - make sure you can't retrieve it anymore
209      */
210     public void testGetAndPut(){
211 
212         VolatilityEnum volatility1 = VolatilityEnum.STABLE;
213         CacheReasonEnum[] reasons1 = new CacheReasonEnum[] { CacheReasonEnum.PRE_FETCH };
214         try{
215             trackChunk(myChunk1Query);
216             myHibernateChunkStore.put(myChunk1Query, volatility1, reasons1);
217         }
218         catch(AssertionError e){
219             fail("AssertionError must not be thrown");
220         }
221         
222         IChunk obtained = null;
223         
224         try{
225             obtained = myHibernateChunkStore.get(myChunk1Query);
226         }
227         catch(AssertionError e){
228             fail("AssertionError must not be thrown");
229         }
230 
231         assert(obtained != null);
232         assertEquals(obtained.getVolatility(), volatility1);
233         ArrayAssert.assertEquals(obtained.getReasons(), reasons1);
234         
235                     
236         VolatilityEnum volatility2 = VolatilityEnum.VOLATILE;
237         CacheReasonEnum[] reasons2 = new CacheReasonEnum[] { CacheReasonEnum.PRE_FETCH, CacheReasonEnum.QUERY };
238         try{
239             trackChunk(myChunk2Query);
240             myHibernateChunkStore.put(myChunk2Query, volatility2, reasons2);
241 
242         }
243         catch(AssertionError e){
244             fail("AssertionError must not be thrown");
245         }
246         
247         obtained = null;
248         
249         try{
250             obtained = myHibernateChunkStore.get(myChunk2Query);
251         }
252         catch(AssertionError e){
253             fail("AssertionError must not be thrown");
254         }
255 
256         assert(obtained != null);
257         assertEquals(obtained.getVolatility(), volatility2);
258         ArrayAssert.assertEquivalenceArrays(obtained.getReasons(), reasons2);
259 
260         obtained = null;
261         
262         // first time we call remove, we should get the previous value returned
263         try{
264             obtained = myHibernateChunkStore.remove(myChunk2Query);
265         }
266         catch(AssertionError e){
267             fail("AssertionError must not be thrown");
268         }
269         
270         assert(obtained != null);
271         assertEquals(obtained.getVolatility(), volatility2);
272         ArrayAssert.assertEquivalenceArrays(obtained.getReasons(), reasons2);
273 
274         obtained = null;
275         
276         // second time we call remove, the previous value returned should be null
277         try{
278             obtained = myHibernateChunkStore.remove(myChunk2Query);
279         }
280         catch(AssertionError e){
281             fail("AssertionError must not be thrown");
282         }
283         
284         assert(obtained == null);
285     }
286     
287     /***
288      */
289     public void testGetStaleChunks1() {
290         myHibernateChunkStore.put( 
291                 myChunk1Query, 
292                 VolatilityEnum.STABLE, 
293                 new CacheReasonEnum[] { CacheReasonEnum.QUERY } );
294         
295         assertFalse( myHibernateChunkStore.getStaleChunks().hasNext() );
296         
297         try { Thread.sleep(1500); } catch (InterruptedException e) {}
298 
299         //will become stale after 1 second (see the rule in the spring config file)
300         assertTrue( myHibernateChunkStore.getStaleChunks().hasNext() ); 
301     }
302 
303     /***
304      * Marks a <b>Chunk</b> to be removed from the storage by the <code>tearDown</code> method.
305      * 
306      * @param theQuery
307      *            The <b>Chunk</b> to mark.
308      */
309     void trackChunk( IQuery theQuery ) {
310         if ( !myTrackedChunks.contains( theQuery )) {
311             myTrackedChunks.add( theQuery );
312         }
313     }
314     
315 }
316