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