View Javadoc
1   package org.apache.commons.jcs.engine.control;
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.io.IOException;
23  import java.util.Collections;
24  import java.util.HashMap;
25  import java.util.Map;
26  import java.util.Set;
27  
28  import junit.framework.TestCase;
29  
30  import org.apache.commons.jcs.JCS;
31  import org.apache.commons.jcs.access.CacheAccess;
32  import org.apache.commons.jcs.access.exception.CacheException;
33  import org.apache.commons.jcs.auxiliary.AbstractAuxiliaryCache;
34  import org.apache.commons.jcs.auxiliary.AuxiliaryCache;
35  import org.apache.commons.jcs.auxiliary.AuxiliaryCacheAttributes;
36  import org.apache.commons.jcs.engine.CacheElement;
37  import org.apache.commons.jcs.engine.CacheStatus;
38  import org.apache.commons.jcs.engine.CompositeCacheAttributes;
39  import org.apache.commons.jcs.engine.ElementAttributes;
40  import org.apache.commons.jcs.engine.behavior.ICacheElement;
41  import org.apache.commons.jcs.engine.behavior.ICacheType.CacheType;
42  import org.apache.commons.jcs.engine.behavior.ICompositeCacheAttributes;
43  import org.apache.commons.jcs.engine.behavior.IElementAttributes;
44  import org.apache.commons.jcs.engine.behavior.IElementSerializer;
45  import org.apache.commons.jcs.engine.logging.behavior.ICacheEventLogger;
46  import org.apache.commons.jcs.engine.stats.behavior.IStats;
47  
48  /**
49   * Tests of the disk usage settings for the CompositeCache.
50   * <p>
51   * @author Aaron Smuts
52   */
53  public class CompositeCacheDiskUsageUnitTest
54      extends TestCase
55  {
56      private static final String CACHE_NAME = "testSpoolAllowed";
57  
58      /**
59       * Test setup
60       */
61      @Override
62      public void setUp()
63      {
64          JCS.setConfigFilename( "/TestDiskCacheUsagePattern.ccf" );
65      }
66  
67      /**
68       * Verify that the swap region is set to the correct pattern.
69       * <p>
70       * @throws CacheException
71       */
72      public void testSwapConfig()
73          throws CacheException
74      {
75          CacheAccess<String, String> swap = JCS.getInstance( "Swap" );
76          assertEquals( ICompositeCacheAttributes.DiskUsagePattern.SWAP, swap.getCacheAttributes()
77              .getDiskUsagePattern() );
78      }
79  
80      /**
81       * Verify that the swap region is set to the correct pattern.
82       * <p>
83       * @throws CacheException
84       */
85      public void testUpdateConfig()
86          throws CacheException
87      {
88          CacheAccess<String, String> swap = JCS.getInstance( "Update" );
89          assertEquals( ICompositeCacheAttributes.DiskUsagePattern.UPDATE, swap.getCacheAttributes()
90              .getDiskUsagePattern() );
91      }
92  
93      /**
94       * Setup a disk cache. Configure the disk usage pattern to swap. Call spool. Verify that the
95       * item is put to disk.
96       */
97      public void testSpoolAllowed()
98      {
99          // SETUP
100         ICompositeCacheAttributes cattr = new CompositeCacheAttributes();
101         cattr.setCacheName(CACHE_NAME);
102         cattr.setDiskUsagePattern( ICompositeCacheAttributes.DiskUsagePattern.SWAP );
103 
104         IElementAttributes attr = new ElementAttributes();
105 
106         CompositeCache<String, String> cache = new CompositeCache<String, String>( cattr, attr );
107 
108         MockAuxCache<String, String> mock = new MockAuxCache<String, String>();
109         mock.cacheType = CacheType.DISK_CACHE;
110 
111         @SuppressWarnings("unchecked")
112         AuxiliaryCache<String, String>[] auxArray = new AuxiliaryCache[] { mock };
113         cache.setAuxCaches( auxArray );
114 
115         ICacheElement<String, String> inputElement = new CacheElement<String, String>( CACHE_NAME, "key", "value" );
116 
117         // DO WORK
118         cache.spoolToDisk( inputElement );
119 
120         // VERIFY
121         assertEquals( "Wrong number of calls to the disk cache update.", 1, mock.updateCount );
122         assertEquals( "Wrong element updated.", inputElement, mock.lastUpdatedItem );
123     }
124 
125     /**
126      * Setup a disk cache. Configure the disk usage pattern to not swap. Call spool. Verify that the
127      * item is not put to disk.
128      */
129     public void testSpoolNotAllowed()
130     {
131         // SETUP
132         ICompositeCacheAttributes cattr = new CompositeCacheAttributes();
133         cattr.setCacheName(CACHE_NAME);
134         cattr.setDiskUsagePattern( ICompositeCacheAttributes.DiskUsagePattern.UPDATE );
135 
136         IElementAttributes attr = new ElementAttributes();
137 
138         CompositeCache<String, String> cache = new CompositeCache<String, String>( cattr, attr );
139 
140         MockAuxCache<String, String> mock = new MockAuxCache<String, String>();
141         mock.cacheType = CacheType.DISK_CACHE;
142 
143         @SuppressWarnings("unchecked")
144         AuxiliaryCache<String, String>[] auxArray = new AuxiliaryCache[] { mock };
145         cache.setAuxCaches( auxArray );
146 
147         ICacheElement<String, String> inputElement = new CacheElement<String, String>( CACHE_NAME, "key", "value" );
148 
149         // DO WORK
150         cache.spoolToDisk( inputElement );
151 
152         // VERIFY
153         assertEquals( "Wrong number of calls to the disk cache update.", 0, mock.updateCount );
154     }
155 
156     /**
157      * Setup a disk cache. Configure the disk usage pattern to UPDATE. Call updateAuxiliaries.
158      * Verify that the item is put to disk.
159      * <p>
160      * This tests that the items are put to disk on a normal put when the usage pattern is set
161      * appropriately.
162      * @throws IOException
163      */
164     public void testUpdateAllowed()
165         throws IOException
166     {
167         // SETUP
168         ICompositeCacheAttributes cattr = new CompositeCacheAttributes();
169         cattr.setCacheName(CACHE_NAME);
170         cattr.setDiskUsagePattern( ICompositeCacheAttributes.DiskUsagePattern.UPDATE );
171 
172         IElementAttributes attr = new ElementAttributes();
173 
174         CompositeCache<String, String> cache = new CompositeCache<String, String>( cattr, attr );
175 
176         MockAuxCache<String, String> mock = new MockAuxCache<String, String>();
177         mock.cacheType = CacheType.DISK_CACHE;
178 
179         @SuppressWarnings("unchecked")
180         AuxiliaryCache<String, String>[] auxArray = new AuxiliaryCache[] { mock };
181         cache.setAuxCaches( auxArray );
182 
183         ICacheElement<String, String> inputElement = new CacheElement<String, String>( CACHE_NAME, "key", "value" );
184 
185         // DO WORK
186         cache.updateAuxiliaries( inputElement, true );
187 
188         // VERIFY
189         assertEquals( "Wrong number of calls to the disk cache update.", 1, mock.updateCount );
190         assertEquals( "Wrong element updated.", inputElement, mock.lastUpdatedItem );
191     }
192 
193     /**
194      * Setup a disk cache. Configure the disk usage pattern to UPDATE. Call updateAuxiliaries with
195      * local only set to false. Verify that the item is put to disk.
196      * <p>
197      * This tests that the items are put to disk on a normal put when the usage pattern is set
198      * appropriately. The local setting should have no impact on whether the item goes to disk.
199      * <p>
200      * @throws IOException
201      */
202     public void testUpdateAllowed_localFalse()
203         throws IOException
204     {
205         // SETUP
206         ICompositeCacheAttributes cattr = new CompositeCacheAttributes();
207         cattr.setCacheName(CACHE_NAME);
208         cattr.setDiskUsagePattern( ICompositeCacheAttributes.DiskUsagePattern.UPDATE );
209 
210         IElementAttributes attr = new ElementAttributes();
211 
212         CompositeCache<String, String> cache = new CompositeCache<String, String>( cattr, attr );
213 
214         MockAuxCache<String, String> mock = new MockAuxCache<String, String>();
215         mock.cacheType = CacheType.DISK_CACHE;
216 
217         @SuppressWarnings("unchecked")
218         AuxiliaryCache<String, String>[] auxArray = new AuxiliaryCache[] { mock };
219         cache.setAuxCaches( auxArray );
220 
221         ICacheElement<String, String> inputElement = new CacheElement<String, String>( CACHE_NAME, "key", "value" );
222 
223         // DO WORK
224         cache.updateAuxiliaries( inputElement, false );
225 
226         // VERIFY
227         assertEquals( "Wrong number of calls to the disk cache update.", 1, mock.updateCount );
228         assertEquals( "Wrong element updated.", inputElement, mock.lastUpdatedItem );
229     }
230 
231     /**
232      * Setup a disk cache. Configure the disk usage pattern to SWAP. Call updateAuxiliaries. Verify
233      * that the item is not put to disk.
234      * <p>
235      * This tests that the items are not put to disk on a normal put when the usage pattern is set
236      * to SWAP.
237      * <p>
238      * @throws IOException
239      */
240     public void testUpdateNotAllowed()
241         throws IOException
242     {
243         // SETUP
244         ICompositeCacheAttributes cattr = new CompositeCacheAttributes();
245         cattr.setCacheName(CACHE_NAME);
246         cattr.setDiskUsagePattern( ICompositeCacheAttributes.DiskUsagePattern.SWAP );
247 
248         IElementAttributes attr = new ElementAttributes();
249 
250         CompositeCache<String, String> cache = new CompositeCache<String, String>( cattr, attr );
251 
252         MockAuxCache<String, String> mock = new MockAuxCache<String, String>();
253         mock.cacheType = CacheType.DISK_CACHE;
254 
255         @SuppressWarnings("unchecked")
256         AuxiliaryCache<String, String>[] auxArray = new AuxiliaryCache[] { mock };
257         cache.setAuxCaches( auxArray );
258 
259         ICacheElement<String, String> inputElement = new CacheElement<String, String>( CACHE_NAME, "key", "value" );
260 
261         // DO WORK
262         cache.updateAuxiliaries( inputElement, true );
263 
264         // VERIFY
265         assertEquals( "Wrong number of calls to the disk cache update.", 0, mock.updateCount );
266     }
267 
268     /**
269      * Setup a disk cache. Configure the disk usage pattern to UPDATE. Call updateAuxiliaries.
270      * Verify that the item is put to disk.
271      * <p>
272      * This tests that the items are put to disk on a normal put when the usage pattern is set
273      * appropriately.
274      * @throws IOException
275      */
276     public void testUpdateAllowed_withOtherCaches()
277         throws IOException
278     {
279         // SETUP
280         ICompositeCacheAttributes cattr = new CompositeCacheAttributes();
281         cattr.setCacheName(CACHE_NAME);
282         cattr.setDiskUsagePattern( ICompositeCacheAttributes.DiskUsagePattern.UPDATE );
283 
284         IElementAttributes attr = new ElementAttributes();
285 
286         CompositeCache<String, String> cache = new CompositeCache<String, String>( cattr, attr );
287 
288         MockAuxCache<String, String> mock = new MockAuxCache<String, String>();
289         mock.cacheType = CacheType.DISK_CACHE;
290 
291         MockAuxCache<String, String> mockLateral = new MockAuxCache<String, String>();
292         mockLateral.cacheType = CacheType.LATERAL_CACHE;
293 
294         @SuppressWarnings("unchecked")
295         AuxiliaryCache<String, String>[] auxArray = new AuxiliaryCache[] { mock, mockLateral };
296         cache.setAuxCaches( auxArray );
297 
298         ICacheElement<String, String> inputElement = new CacheElement<String, String>( CACHE_NAME, "key", "value" );
299 
300         // DO WORK
301         cache.updateAuxiliaries( inputElement, false );
302 
303         // VERIFY
304         assertEquals( "Wrong number of calls to the disk cache update.", 1, mock.updateCount );
305         assertEquals( "Wrong element updated.", inputElement, mock.lastUpdatedItem );
306 
307         assertEquals( "Wrong number of calls to the lateral cache update.", 1, mockLateral.updateCount );
308         assertEquals( "Wrong element updated with lateral.", inputElement, mockLateral.lastUpdatedItem );
309     }
310 
311     /**
312      * Used to test the disk cache functionality.
313      * <p>
314      * @author Aaron Smuts
315      */
316     public static class MockAuxCache<K, V>
317         extends AbstractAuxiliaryCache<K, V>
318     {
319         /** The last item passed to update. */
320         public ICacheElement<K, V> lastUpdatedItem;
321 
322         /** The number of times update was called. */
323         public int updateCount = 0;
324 
325         /** The type that should be returned from getCacheType. */
326         public CacheType cacheType = CacheType.DISK_CACHE;
327 
328         /** Resets counters and catchers. */
329         public void reset()
330         {
331             updateCount = 0;
332             lastUpdatedItem = null;
333         }
334 
335         /**
336          * @param ce
337          * @throws IOException
338          */
339         @Override
340         public void update( ICacheElement<K, V> ce )
341             throws IOException
342         {
343             lastUpdatedItem = ce;
344             updateCount++;
345         }
346 
347         /**
348          * @param key
349          * @return ICacheElement
350          * @throws IOException
351          */
352         @Override
353         public ICacheElement<K, V> get( K key )
354             throws IOException
355         {
356             return null;
357         }
358 
359         /**
360          * Gets multiple items from the cache based on the given set of keys.
361          * <p>
362          * @param keys
363          * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is
364          *         no data in cache for any of these keys
365          */
366         @Override
367         public Map<K, ICacheElement<K, V>> getMultiple(Set<K> keys)
368         {
369             return new HashMap<K, ICacheElement<K, V>>();
370         }
371 
372         /**
373          * @param key
374          * @return false
375          * @throws IOException
376          */
377         @Override
378         public boolean remove( K key )
379             throws IOException
380         {
381             return false;
382         }
383 
384         /** @throws IOException */
385         @Override
386         public void removeAll()
387             throws IOException
388         {
389             // noop
390         }
391 
392         /** @throws IOException */
393         @Override
394         public void dispose()
395             throws IOException
396         {
397             // noop
398         }
399 
400         /** @return 0 */
401         @Override
402         public int getSize()
403         {
404             return 0;
405         }
406 
407         /** @return 0 */
408         @Override
409         public CacheStatus getStatus()
410         {
411             return CacheStatus.ALIVE;
412         }
413 
414         /** @return null */
415         @Override
416         public String getCacheName()
417         {
418             return null;
419         }
420 
421         /**
422          * @return null
423          * @throws IOException
424          */
425         @Override
426         public Set<K> getKeySet( )
427             throws IOException
428         {
429             return null;
430         }
431 
432         /** @return null */
433         @Override
434         public IStats getStatistics()
435         {
436             return null;
437         }
438 
439         /** @return null */
440         @Override
441         public String getStats()
442         {
443             return null;
444         }
445 
446         /**
447          * Returns the setup cache type. This allows you to use this mock as multiple cache types.
448          * <p>
449          * @see org.apache.commons.jcs.engine.behavior.ICacheType#getCacheType()
450          * @return cacheType
451          */
452         @Override
453         public CacheType getCacheType()
454         {
455             return cacheType;
456         }
457 
458         /**
459          * @return Returns the AuxiliaryCacheAttributes.
460          */
461         @Override
462         public AuxiliaryCacheAttributes getAuxiliaryCacheAttributes()
463         {
464             return null;
465         }
466 
467         /**
468          * @param cacheEventLogger
469          */
470         @Override
471         public void setCacheEventLogger( ICacheEventLogger cacheEventLogger )
472         {
473             // TODO Auto-generated method stub
474 
475         }
476 
477         /**
478          * @param elementSerializer
479          */
480         @Override
481         public void setElementSerializer( IElementSerializer elementSerializer )
482         {
483             // TODO Auto-generated method stub
484 
485         }
486 
487         /** @return null */
488         @Override
489         public String getEventLoggingExtraInfo()
490         {
491             // TODO Auto-generated method stub
492             return null;
493         }
494 
495         /**
496          * @param pattern
497          * @return Collections.EMPTY_MAP;
498          * @throws IOException
499          */
500         @Override
501         public Map<K, ICacheElement<K, V>> getMatching(String pattern)
502             throws IOException
503         {
504             return Collections.emptyMap();
505         }
506 
507 
508     }
509 
510 }