1   package org.apache.jcs.auxiliary.disk.jdbc;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.sql.Connection;
23  import java.sql.DriverManager;
24  import java.sql.SQLException;
25  import java.sql.Statement;
26  import java.util.Properties;
27  
28  import junit.framework.TestCase;
29  
30  import org.apache.jcs.JCS;
31  import org.apache.jcs.access.exception.CacheException;
32  import org.apache.jcs.utils.timing.SleepUtil;
33  
34  /***
35   * Runs basic tests for the JDBC disk cache.
36   * <p>
37   * @author Aaron Smuts
38   */
39  public class JDBCDiskCacheShrinkUnitTest
40      extends TestCase
41  {
42  
43      /***
44       * Test setup
45       * <p>
46       * @throws ClassNotFoundException
47       * @throws IllegalAccessException
48       * @throws InstantiationException
49       * @throws SQLException
50       */
51      public void setUp()
52          throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException
53      {
54          JCS.setConfigFilename( "/TestJDBCDiskCacheShrink.ccf" );
55  
56          System.setProperty( "hsqldb.cache_scale", "8" );
57  
58          String rafroot = "target";
59          Properties p = new Properties();
60          String driver = p.getProperty( "driver", "org.hsqldb.jdbcDriver" );
61          String url = p.getProperty( "url", "jdbc:hsqldb:" );
62          String database = p.getProperty( "database", rafroot + "/JDBCDiskCacheShrinkUnitTest" );
63          String user = p.getProperty( "user", "sa" );
64          String password = p.getProperty( "password", "" );
65  
66          new org.hsqldb.jdbcDriver();
67          Class.forName( driver ).newInstance();
68          Connection cConn = DriverManager.getConnection( url + database, user, password );
69  
70          setupTABLE( cConn );
71      }
72  
73      /***
74       * Test the basic JDBC disk cache functionality with a hsql backing. Verify that items
75       * configured to expire after 1 second actually expire.
76       * <p>
77       * @throws Exception
78       */
79      public void testExpireInBackground()
80          throws Exception
81      {
82          String regionExpire = "expire1Second";
83          int items = 200;
84  
85          JCS jcsExpire = JCS.getInstance( regionExpire );
86  
87          System.out.println( "BEFORE PUT \n" + jcsExpire.getStats() );
88  
89          // Add items to cache
90  
91          for ( int i = 0; i <= items; i++ )
92          {
93              jcsExpire.put( i + ":key", regionExpire + " data " + i );
94          }
95  
96          System.out.println( jcsExpire.getStats() );
97  
98          // the shrinker is supposed to run every second
99          SleepUtil.sleepAtLeast( 3000 );
100 
101         System.out.println( jcsExpire.getStats() );
102 
103         // Test that all items have been removed from the cache
104         for ( int i = 0; i <= items; i++ )
105         {
106             assertNull( "Removed key should be null: " + i + ":key", jcsExpire.get( i + ":key" ) );
107         }
108     }
109 
110     /***
111      * Verify that those not scheduled to expire do not expire.
112      * <p>
113      * @throws CacheException
114      * @throws InterruptedException
115      */
116     public void testDidNotExpire()
117         throws CacheException, InterruptedException
118     {
119         String region = "expire100Second";
120         int items = 200;
121 
122         JCS jcs = JCS.getInstance( region );
123 
124         System.out.println( "BEFORE PUT \n" + jcs.getStats() );
125 
126         // Add items to cache
127 
128         for ( int i = 0; i <= items; i++ )
129         {
130             jcs.put( i + ":key", region + " data " + i );
131         }
132 
133         System.out.println( jcs.getStats() );
134 
135         SleepUtil.sleepAtLeast( 1000 );
136 
137         System.out.println( jcs.getStats() );
138 
139         // Test that all items are in cache
140 
141         for ( int i = 0; i <= items; i++ )
142         {
143             String value = (String) jcs.get( i + ":key" );
144 
145             assertEquals( "key = [" + i + ":key] value = [" + value + "]", region + " data " + i, value );
146         }
147 
148         // Remove all the items
149 
150         for ( int i = 0; i <= items; i++ )
151         {
152             jcs.remove( i + ":key" );
153         }
154 
155         // Verify removal
156 
157         for ( int i = 0; i <= items; i++ )
158         {
159             assertNull( "Removed key should be null: " + i + ":key", jcs.get( i + ":key" ) );
160         }
161     }
162 
163     /***
164      * Verify that eternal trumps max life.
165      * @throws CacheException
166      * @throws InterruptedException
167      */
168     public void testDidNotExpireEternal()
169         throws CacheException, InterruptedException
170     {
171         String region = "eternal";
172         int items = 200;
173 
174         JCS jcs = JCS.getInstance( region );
175 
176         System.out.println( "BEFORE PUT \n" + jcs.getStats() );
177 
178         // Add items to cache
179 
180         for ( int i = 0; i <= items; i++ )
181         {
182             jcs.put( i + ":key", region + " data " + i );
183         }
184 
185         System.out.println( jcs.getStats() );
186 
187         SleepUtil.sleepAtLeast( 1000 );
188 
189         System.out.println( jcs.getStats() );
190 
191         // Test that all items are in cache
192 
193         for ( int i = 0; i <= items; i++ )
194         {
195             String value = (String) jcs.get( i + ":key" );
196 
197             assertEquals( "key = [" + i + ":key] value = [" + value + "]", region + " data " + i, value );
198         }
199 
200         // Remove all the items
201 
202         for ( int i = 0; i <= items; i++ )
203         {
204             jcs.remove( i + ":key" );
205         }
206 
207         // Verify removal
208 
209         for ( int i = 0; i <= items; i++ )
210         {
211             assertNull( "Removed key should be null: " + i + ":key", jcs.get( i + ":key" ) );
212         }
213     }
214 
215     /***
216      * SETUP TABLE FOR CACHE
217      * @param cConn
218      */
219     void setupTABLE( Connection cConn )
220     {
221         boolean newT = true;
222 
223         StringBuffer createSql = new StringBuffer();
224         createSql.append( "CREATE CACHED TABLE JCS_STORE_SHRINK " );
225         createSql.append( "( " );
226         createSql.append( "CACHE_KEY             VARCHAR(250)          NOT NULL, " );
227         createSql.append( "REGION                VARCHAR(250)          NOT NULL, " );
228         createSql.append( "ELEMENT               BINARY, " );
229         createSql.append( "CREATE_TIME           DATE, " );
230         createSql.append( "CREATE_TIME_SECONDS   BIGINT, " );
231         createSql.append( "MAX_LIFE_SECONDS      BIGINT, " );
232         createSql.append( "SYSTEM_EXPIRE_TIME_SECONDS      BIGINT, " );
233         createSql.append( "IS_ETERNAL            CHAR(1), " );
234         createSql.append( "PRIMARY KEY (CACHE_KEY, REGION) " );
235         createSql.append( ");" );
236 
237         Statement sStatement = null;
238         try
239         {
240             sStatement = cConn.createStatement();
241         }
242         catch ( SQLException e )
243         {
244             e.printStackTrace();
245         }
246 
247         try
248         {
249             sStatement.executeQuery( createSql.toString() );
250             sStatement.close();
251         }
252         catch ( SQLException e )
253         {
254             if ( e.toString().indexOf( "already exists" ) != -1 )
255             {
256                 newT = false;
257             }
258             else
259             {
260                 // TODO figure out if it exists prior to trying to create it.
261                 // log.error( "Problem creating table.", e );
262                 e.printStackTrace();
263             }
264         }
265 
266         String setupData[] = { "create index iKEY on JCS_STORE_SHRINK (CACHE_KEY, REGION)" };
267 
268         if ( newT )
269         {
270             for ( int i = 1; i < setupData.length; i++ )
271             {
272                 try
273                 {
274                     sStatement.executeQuery( setupData[i] );
275                 }
276                 catch ( SQLException e )
277                 {
278                     System.out.println( "Exception: " + e );
279                 }
280             }
281         } // end ifnew
282     }
283 }