1   package org.apache.jcs.utils.struct;
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.util.Iterator;
23  
24  import junit.framework.Test;
25  import junit.framework.TestCase;
26  import junit.framework.TestSuite;
27  
28  import org.apache.jcs.utils.struct.LRUMap;
29  
30  /***
31   * Tests the LRUMap
32   * <p>
33   * @author aaron smuts
34   *
35   */
36  public class LRUMapConcurrentUnitTest
37      extends TestCase
38  {
39      /*** number to test with */
40      private static int items = 20000;
41  
42      /***
43       * Constructor for the TestSimpleLoad object
44       * <p>
45       * @param testName
46       *            Description of the Parameter
47       */
48      public LRUMapConcurrentUnitTest( String testName )
49      {
50          super( testName );
51      }
52  
53      /***
54       * A unit test suite for JUnit
55       * <p>
56       * @return The test suite
57       */
58      public static Test suite()
59      {
60          // run the basic tests
61          TestSuite suite = new TestSuite( LRUMapConcurrentUnitTest.class );
62  
63          // run concurrent tests
64          final LRUMap map = new LRUMap( 2000 );
65          suite.addTest( new LRUMapConcurrentUnitTest( "conc1" )
66          {
67              public void runTest()
68                  throws Exception
69              {
70                  this.runConcurrentPutGetTests( map, 2000 );
71              }
72          } );
73          suite.addTest( new LRUMapConcurrentUnitTest( "conc2" )
74          {
75              public void runTest()
76                  throws Exception
77              {
78                  this.runConcurrentPutGetTests( map, 2000 );
79              }
80          } );
81          suite.addTest( new LRUMapConcurrentUnitTest( "conc3" )
82          {
83              public void runTest()
84                  throws Exception
85              {
86                  this.runConcurrentPutGetTests( map, 2000 );
87              }
88          } );
89  
90          // run more concurrent tests
91          final int max2 = 20000;
92          final LRUMap map2 = new LRUMap( max2 );
93          suite.addTest( new LRUMapConcurrentUnitTest( "concB1" )
94          {
95              public void runTest()
96                  throws Exception
97              {
98                  this.runConcurrentRangeTests( map2, 10000, max2 );
99              }
100         } );
101         suite.addTest( new LRUMapConcurrentUnitTest( "concB1" )
102         {
103             public void runTest()
104                 throws Exception
105             {
106                 this.runConcurrentRangeTests( map2, 0, 9999 );
107             }
108         } );
109 
110         return suite;
111     }
112 
113     /***
114      * Just test that we can put, get and remove as expected.
115      * <p>
116      * @exception Exception
117      *                Description of the Exception
118      */
119     public void testSimpleLoad()
120         throws Exception
121     {
122         LRUMap map = new LRUMap( items );
123 
124         for ( int i = 0; i < items; i++ )
125         {
126             map.put( i + ":key", "data" + i );
127         }
128 
129         for ( int i = items - 1; i >= 0; i-- )
130         {
131             String res = (String) map.get( i + ":key" );
132             if ( res == null )
133             {
134                 assertNotNull( "[" + i + ":key] should not be null", res );
135             }
136         }
137 
138         // test removal
139         map.remove( "300:key" );
140         assertNull( map.get( "300:key" ) );
141 
142     }
143 
144     /***
145      * Just make sure that the LRU functions int he most simple case.
146      *
147      * @exception Exception
148      *                Description of the Exception
149      */
150     public void testLRURemoval()
151         throws Exception
152     {
153         int total = 10;
154         LRUMap map = new LRUMap( total );
155         map.setChunkSize( 1 );
156 
157         // put the max in
158         for ( int i = 0; i < total; i++ )
159         {
160             map.put( i + ":key", "data" + i );
161         }
162 
163         Iterator it = map.entrySet().iterator();
164         while ( it.hasNext() )
165         {
166             System.out.println( it.next() );
167         }
168         System.out.println( map.getStatistics() );
169 
170         // get the max out backwards
171         for ( int i = total - 1; i >= 0; i-- )
172         {
173             String res = (String) map.get( i + ":key" );
174             if ( res == null )
175             {
176                 assertNotNull( "[" + i + ":key] should not be null", res );
177             }
178         }
179 
180         System.out.println( map.getStatistics() );
181 
182         //since we got them backwards the total should be at the end.
183         // add one confirm that total is gone.
184         map.put( ( total ) + ":key", "data" + ( total ) );
185         assertNull( map.get( ( total - 1 ) + ":key" ) );
186 
187     }
188 
189     /***
190      * @throws Exception
191      */
192     public void testLRURemovalAgain()
193         throws Exception
194     {
195         int total = 10000;
196         LRUMap map = new LRUMap( total );
197         map.setChunkSize( 1 );
198 
199         // put the max in
200         for ( int i = 0; i < total * 2; i++ )
201         {
202             map.put( i + ":key", "data" + i );
203         }
204 
205         // get the total number, these shoukld be null
206         for ( int i = total - 1; i >= 0; i-- )
207         {
208             assertNull( map.get( i + ":key" ) );
209 
210         }
211 
212         // get the total to total *2 items out, these should be foufn.
213         for ( int i = ( total * 2 ) - 1; i >= total; i-- )
214         {
215             String res = (String) map.get( i + ":key" );
216             if ( res == null )
217             {
218                 assertNotNull( "[" + i + ":key] should not be null", res );
219             }
220         }
221 
222         System.out.println( map.getStatistics() );
223 
224     }
225 
226     /***
227      * Just make sure that we can put and get concurrently
228      *
229      * @param map
230      * @param items
231      * @throws Exception
232      */
233     public void runConcurrentPutGetTests( LRUMap map, int items )
234         throws Exception
235     {
236         for ( int i = 0; i < items; i++ )
237         {
238             map.put( i + ":key", "data" + i );
239         }
240 
241         for ( int i = items - 1; i >= 0; i-- )
242         {
243             String res = (String) map.get( i + ":key" );
244             if ( res == null )
245             {
246                 assertNotNull( "[" + i + ":key] should not be null", res );
247             }
248         }
249 
250     }
251 
252     /***
253      * Put, get, and remove from a range. This should occur at a range that is
254      * not touched by other tests.
255      * <p>
256      * @param map
257      * @param start
258      * @param end
259      * @throws Exception
260      */
261     public void runConcurrentRangeTests( LRUMap map, int start, int end )
262         throws Exception
263     {
264         for ( int i = start; i < end; i++ )
265         {
266             map.put( i + ":key", "data" + i );
267         }
268 
269         for ( int i = end - 1; i >= start; i-- )
270         {
271             String res = (String) map.get( i + ":key" );
272             if ( res == null )
273             {
274                 assertNotNull( "[" + i + ":key] should not be null", res );
275             }
276         }
277 
278         // test removal
279         map.remove( start + ":key" );
280         assertNull( map.get( start + ":key" ) );
281     }
282 }