View Javadoc
1   package org.apache.commons.jcs3.auxiliary.disk.indexed;
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.nio.charset.StandardCharsets;
24  import java.util.HashSet;
25  import java.util.Map;
26  import java.util.Set;
27  
28  import org.apache.commons.jcs3.auxiliary.MockCacheEventLogger;
29  import org.apache.commons.jcs3.auxiliary.disk.DiskTestObject;
30  import org.apache.commons.jcs3.engine.CacheElement;
31  import org.apache.commons.jcs3.engine.ElementAttributes;
32  import org.apache.commons.jcs3.engine.behavior.ICacheElement;
33  import org.apache.commons.jcs3.engine.behavior.IElementAttributes;
34  import org.apache.commons.jcs3.engine.control.group.GroupAttrName;
35  import org.apache.commons.jcs3.engine.control.group.GroupId;
36  import org.apache.commons.jcs3.utils.timing.SleepUtil;
37  
38  import junit.framework.TestCase;
39  
40  /**
41   * Tests for common functionality.
42   */
43  public abstract class IndexDiskCacheUnitTestAbstract extends TestCase
44  {
45      public abstract IndexedDiskCacheAttributes getCacheAttributes();
46  
47      /**
48       * Simply verify that we can put items in the disk cache and retrieve them.
49       *
50       * @throws IOException
51       */
52      public void testSimplePutAndGet() throws IOException
53      {
54          final IndexedDiskCacheAttributes cattr = getCacheAttributes();
55          cattr.setCacheName("testSimplePutAndGet");
56          cattr.setMaxKeySize(1000);
57          cattr.setDiskPath("target/test-sandbox/IndexDiskCacheUnitTest");
58          final IndexedDiskCache<String, String> disk = new IndexedDiskCache<>(cattr);
59  
60          disk.processRemoveAll();
61  
62          final int cnt = 999;
63          for (int i = 0; i < cnt; i++)
64          {
65              final IElementAttributes eAttr = new ElementAttributes();
66              eAttr.setIsSpool(true);
67              final ICacheElement<String, String> element = new CacheElement<>("testSimplePutAndGet", "key:" + i, "data:" + i);
68              element.setElementAttributes(eAttr);
69              disk.processUpdate(element);
70          }
71  
72          for (int i = 0; i < cnt; i++)
73          {
74              final ICacheElement<String, String> element = disk.processGet("key:" + i);
75              assertNotNull("Should have received an element.", element);
76              assertEquals("Element is wrong.", "data:" + i, element.getVal());
77          }
78  
79          // Test that getMultiple returns all the expected values
80          final Set<String> keys = new HashSet<>();
81          for (int i = 0; i < cnt; i++)
82          {
83              keys.add("key:" + i);
84          }
85  
86          final Map<String, ICacheElement<String, String>> elements = disk.getMultiple(keys);
87          for (int i = 0; i < cnt; i++)
88          {
89              final ICacheElement<String, String> element = elements.get("key:" + i);
90              assertNotNull("element " + i + ":key is missing", element);
91              assertEquals("value key:" + i, "data:" + i, element.getVal());
92          }
93          // System.out.println( disk.getStats() );
94      }
95  
96      /**
97       * Add some items to the disk cache and then remove them one by one.
98       *
99       * @throws IOException
100      */
101     public void testRemoveItems() throws IOException
102     {
103         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
104         cattr.setCacheName("testRemoveItems");
105         cattr.setMaxKeySize(100);
106         cattr.setDiskPath("target/test-sandbox/IndexDiskCacheUnitTest");
107         final IndexedDiskCache<String, String> disk = new IndexedDiskCache<>(cattr);
108 
109         disk.processRemoveAll();
110 
111         final int cnt = 25;
112         for (int i = 0; i < cnt; i++)
113         {
114             final IElementAttributes eAttr = new ElementAttributes();
115             eAttr.setIsSpool(true);
116             final ICacheElement<String, String> element = new CacheElement<>("testRemoveItems", "key:" + i, "data:" + i);
117             element.setElementAttributes(eAttr);
118             disk.processUpdate(element);
119         }
120 
121         // remove each
122         for (int i = 0; i < cnt; i++)
123         {
124             disk.remove("key:" + i);
125             final ICacheElement<String, String> element = disk.processGet("key:" + i);
126             assertNull("Should not have received an element.", element);
127         }
128     }
129 
130     /**
131      * Verify that we don't override the largest item.
132      * <p>
133      *
134      * @throws IOException
135      */
136 
137     /**
138      * Verify that the overlap check returns true when there are no overlaps.
139      */
140     public void testCheckForDedOverlaps_noOverlap()
141     {
142         // SETUP
143         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
144         cattr.setCacheName("testCheckForDedOverlaps_noOverlap");
145         cattr.setDiskPath("target/test-sandbox/UnitTest");
146         final IndexedDiskCache<String, String> disk = new IndexedDiskCache<>(cattr);
147 
148         final int numDescriptors = 5;
149         int pos = 0;
150         final IndexedDiskElementDescriptor[] sortedDescriptors = new IndexedDiskElementDescriptor[numDescriptors];
151         for (int i = 0; i < numDescriptors; i++)
152         {
153             final IndexedDiskElementDescriptor descriptor = new IndexedDiskElementDescriptor(pos, i * 2);
154             pos = pos + (i * 2) + IndexedDisk.HEADER_SIZE_BYTES;
155             sortedDescriptors[i] = descriptor;
156         }
157 
158         // DO WORK
159         final boolean result = disk.checkForDedOverlaps(sortedDescriptors);
160 
161         // VERIFY
162         assertTrue("There should be no overlap. it should be ok", result);
163     }
164 
165     /**
166      * Verify that the overlap check returns false when there are overlaps.
167      */
168     public void testCheckForDedOverlaps_overlaps()
169     {
170         // SETUP
171         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
172         cattr.setCacheName("testCheckForDedOverlaps_overlaps");
173         cattr.setDiskPath("target/test-sandbox/UnitTest");
174         final IndexedDiskCache<String, String> disk = new IndexedDiskCache<>(cattr);
175 
176         final int numDescriptors = 5;
177         int pos = 0;
178         final IndexedDiskElementDescriptor[] sortedDescriptors = new IndexedDiskElementDescriptor[numDescriptors];
179         for (int i = 0; i < numDescriptors; i++)
180         {
181             final IndexedDiskElementDescriptor descriptor = new IndexedDiskElementDescriptor(pos, i * 2);
182             // don't add the header + IndexedDisk.RECORD_HEADER;
183             pos = pos + (i * 2);
184             sortedDescriptors[i] = descriptor;
185         }
186 
187         // DO WORK
188         final boolean result = disk.checkForDedOverlaps(sortedDescriptors);
189 
190         // VERIFY
191         assertFalse("There should be overlaps. it should be not ok", result);
192     }
193 
194     /**
195      * Verify that the file size is as expected.
196      * <p>
197      *
198      * @throws IOException
199      * @throws InterruptedException
200      */
201     public void testFileSize() throws IOException, InterruptedException
202     {
203         // SETUP
204         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
205         cattr.setCacheName("testFileSize");
206         cattr.setDiskPath("target/test-sandbox/UnitTest");
207         final IndexedDiskCache<Integer, DiskTestObject> disk = new IndexedDiskCache<>(cattr);
208 
209         final int numberToInsert = 20;
210         final int bytes = 24;
211         final ICacheElement<Integer, DiskTestObject>[] elements = DiskTestObjectUtil.createCacheElementsWithTestObjects(numberToInsert,
212             bytes, cattr.getCacheName());
213 
214         for (final ICacheElement<Integer, DiskTestObject> element : elements) {
215             disk.processUpdate(element);
216         }
217 
218         Thread.yield();
219         Thread.sleep(100);
220         Thread.yield();
221 
222         final long expectedSize = DiskTestObjectUtil.totalSize(elements, numberToInsert);
223         final long resultSize = disk.getDataFileSize();
224 
225         // System.out.println( "testFileSize stats " + disk.getStats() );
226 
227         assertEquals("Wrong file size", expectedSize, resultSize);
228     }
229 
230     /**
231      * Verify that items are added to the recycle bin on removal.
232      * <p>
233      *
234      * @throws IOException
235      * @throws InterruptedException
236      */
237     public void testRecyleBinSize() throws IOException, InterruptedException
238     {
239         // SETUP
240         final int numberToInsert = 20;
241 
242         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
243         cattr.setCacheName("testRecyleBinSize");
244         cattr.setDiskPath("target/test-sandbox/UnitTest");
245         cattr.setOptimizeAtRemoveCount(numberToInsert);
246         cattr.setMaxKeySize(numberToInsert * 2);
247         cattr.setMaxPurgatorySize(numberToInsert);
248         final IndexedDiskCache<Integer, DiskTestObject> disk = new IndexedDiskCache<>(cattr);
249 
250         final int bytes = 1;
251         final ICacheElement<Integer, DiskTestObject>[] elements = DiskTestObjectUtil.createCacheElementsWithTestObjects(numberToInsert,
252             bytes, cattr.getCacheName());
253 
254         for (final ICacheElement<Integer, DiskTestObject> element : elements) {
255             disk.processUpdate(element);
256         }
257 
258         Thread.yield();
259         Thread.sleep(100);
260         Thread.yield();
261 
262         // remove half
263         final int numberToRemove = elements.length / 2;
264         for (int i = 0; i < numberToRemove; i++)
265         {
266             disk.processRemove(elements[i].getKey());
267         }
268 
269         // verify that the recycle bin has the correct amount.
270         assertEquals("The recycle bin should have the number removed.", numberToRemove, disk.getRecyleBinSize());
271     }
272 
273     /**
274      * Verify that items of the same size use recycle bin spots. Setup the recycle bin by removing
275      * some items. Add some of the same size. Verify that the recycle count is the number added.
276      * <p>
277      *
278      * @throws IOException
279      * @throws InterruptedException
280      */
281     public void testRecyleBinUsage() throws IOException, InterruptedException
282     {
283         // SETUP
284         final int numberToInsert = 20;
285 
286         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
287         cattr.setCacheName("testRecyleBinUsage");
288         cattr.setDiskPath("target/test-sandbox/UnitTest");
289         cattr.setOptimizeAtRemoveCount(numberToInsert);
290         cattr.setMaxKeySize(numberToInsert * 2);
291         cattr.setMaxPurgatorySize(numberToInsert);
292         final IndexedDiskCache<Integer, DiskTestObject> disk = new IndexedDiskCache<>(cattr);
293 
294         // we will reuse these
295         final int bytes = 1;
296         final ICacheElement<Integer, DiskTestObject>[] elements = DiskTestObjectUtil.createCacheElementsWithTestObjects(numberToInsert,
297             bytes, cattr.getCacheName());
298 
299         // Add some to the disk
300         for (final ICacheElement<Integer, DiskTestObject> element : elements) {
301             disk.processUpdate(element);
302         }
303 
304         Thread.yield();
305         Thread.sleep(100);
306         Thread.yield();
307 
308         // remove half of those added
309         final int numberToRemove = elements.length / 2;
310         for (int i = 0; i < numberToRemove; i++)
311         {
312             disk.processRemove(elements[i].getKey());
313         }
314 
315         // verify that the recycle bin has the correct amount.
316         assertEquals("The recycle bin should have the number removed.", numberToRemove, disk.getRecyleBinSize());
317 
318         // add half as many as we removed. These should all use spots in the recycle bin.
319         final int numberToAdd = numberToRemove / 2;
320         for (int i = 0; i < numberToAdd; i++)
321         {
322             disk.processUpdate(elements[i]);
323         }
324 
325         // verify that we used the correct number of spots
326         assertEquals("The recycle bin should have the number removed." + disk.getStats(), numberToAdd, disk.getRecyleCount());
327     }
328 
329     /**
330      * Verify that the data size is as expected after a remove and after a put that should use the
331      * spots.
332      * <p>
333      *
334      * @throws IOException
335      * @throws InterruptedException
336      */
337     public void testBytesFreeSize() throws IOException, InterruptedException
338     {
339         // SETUP
340         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
341         cattr.setCacheName("testBytesFreeSize");
342         cattr.setDiskPath("target/test-sandbox/UnitTest");
343         final IndexedDiskCache<Integer, DiskTestObject> disk = new IndexedDiskCache<>(cattr);
344 
345         final int numberToInsert = 20;
346         final int bytes = 24;
347         final ICacheElement<Integer, DiskTestObject>[] elements = DiskTestObjectUtil.createCacheElementsWithTestObjects(numberToInsert,
348             bytes, cattr.getCacheName());
349 
350         for (final ICacheElement<Integer, DiskTestObject> element : elements) {
351             disk.processUpdate(element);
352         }
353 
354         Thread.yield();
355         Thread.sleep(100);
356         Thread.yield();
357 
358         // remove half of those added
359         final int numberToRemove = elements.length / 2;
360         for (int i = 0; i < numberToRemove; i++)
361         {
362             disk.processRemove(elements[i].getKey());
363         }
364 
365         final long expectedSize = DiskTestObjectUtil.totalSize(elements, numberToRemove);
366         final long resultSize = disk.getBytesFree();
367 
368         // System.out.println( "testBytesFreeSize stats " + disk.getStats() );
369 
370         assertEquals("Wrong bytes free size" + disk.getStats(), expectedSize, resultSize);
371 
372         // add half as many as we removed. These should all use spots in the recycle bin.
373         final int numberToAdd = numberToRemove / 2;
374         for (int i = 0; i < numberToAdd; i++)
375         {
376             disk.processUpdate(elements[i]);
377         }
378 
379         final long expectedSize2 = DiskTestObjectUtil.totalSize(elements, numberToAdd);
380         final long resultSize2 = disk.getBytesFree();
381         assertEquals("Wrong bytes free size" + disk.getStats(), expectedSize2, resultSize2);
382     }
383 
384     /**
385      * Add some items to the disk cache and then remove them one by one.
386      * <p>
387      *
388      * @throws IOException
389      */
390     public void testRemove_PartialKey() throws IOException
391     {
392         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
393         cattr.setCacheName("testRemove_PartialKey");
394         cattr.setMaxKeySize(100);
395         cattr.setDiskPath("target/test-sandbox/IndexDiskCacheUnitTest");
396         final IndexedDiskCache<String, String> disk = new IndexedDiskCache<>(cattr);
397 
398         disk.processRemoveAll();
399 
400         final int cnt = 25;
401         for (int i = 0; i < cnt; i++)
402         {
403             final IElementAttributes eAttr = new ElementAttributes();
404             eAttr.setIsSpool(true);
405             final ICacheElement<String, String> element = new CacheElement<>("testRemove_PartialKey", i + ":key", "data:"
406                 + i);
407             element.setElementAttributes(eAttr);
408             disk.processUpdate(element);
409         }
410 
411         // verif each
412         for (int i = 0; i < cnt; i++)
413         {
414             final ICacheElement<String, String> element = disk.processGet(i + ":key");
415             assertNotNull("Shoulds have received an element.", element);
416         }
417 
418         // remove each
419         for (int i = 0; i < cnt; i++)
420         {
421             disk.remove(i + ":");
422             final ICacheElement<String, String> element = disk.processGet(i + ":key");
423             assertNull("Should not have received an element.", element);
424         }
425         // https://issues.apache.org/jira/browse/JCS-67
426         assertEquals("Recylenbin should not have more elements than we removed. Check for JCS-67", cnt, disk.getRecyleBinSize());
427     }
428 
429     /**
430      * Verify that group members are removed if we call remove with a group.
431      *
432      * @throws IOException
433      */
434     public void testRemove_Group() throws IOException
435     {
436         // SETUP
437         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
438         cattr.setCacheName("testRemove_Group");
439         cattr.setMaxKeySize(100);
440         cattr.setDiskPath("target/test-sandbox/IndexDiskCacheUnitTest");
441         final IndexedDiskCache<GroupAttrName<String>, String> disk = new IndexedDiskCache<>(cattr);
442 
443         disk.processRemoveAll();
444 
445         final String cacheName = "testRemove_Group_Region";
446         final String groupName = "testRemove_Group";
447 
448         final int cnt = 25;
449         for (int i = 0; i < cnt; i++)
450         {
451             final GroupAttrName<String> groupAttrName = getGroupAttrName(cacheName, groupName, i + ":key");
452             final CacheElement<GroupAttrName<String>, String> element = new CacheElement<>(cacheName,
453                 groupAttrName, "data:" + i);
454 
455             final IElementAttributes eAttr = new ElementAttributes();
456             eAttr.setIsSpool(true);
457             element.setElementAttributes(eAttr);
458 
459             disk.processUpdate(element);
460         }
461 
462         // verify each
463         for (int i = 0; i < cnt; i++)
464         {
465             final GroupAttrName<String> groupAttrName = getGroupAttrName(cacheName, groupName, i + ":key");
466             final ICacheElement<GroupAttrName<String>, String> element = disk.processGet(groupAttrName);
467             assertNotNull("Should have received an element.", element);
468         }
469 
470         // DO WORK
471         // remove the group
472         disk.remove(getGroupAttrName(cacheName, groupName, null));
473 
474         for (int i = 0; i < cnt; i++)
475         {
476             final GroupAttrName<String> groupAttrName = getGroupAttrName(cacheName, groupName, i + ":key");
477             final ICacheElement<GroupAttrName<String>, String> element = disk.processGet(groupAttrName);
478 
479             // VERIFY
480             assertNull("Should not have received an element.", element);
481         }
482 
483     }
484 
485     /**
486      * Internal method used for group functionality.
487      * <p>
488      *
489      * @param cacheName
490      * @param group
491      * @param name
492      * @return GroupAttrName
493      */
494     private GroupAttrName<String> getGroupAttrName(final String cacheName, final String group, final String name)
495     {
496         final GroupId gid = new GroupId(cacheName, group);
497         return new GroupAttrName<>(gid, name);
498     }
499 
500     /**
501      * Verify event log calls.
502      * <p>
503      *
504      * @throws Exception
505      */
506     public void testUpdate_EventLogging_simple() throws Exception
507     {
508         // SETUP
509         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
510         cattr.setCacheName("testUpdate_EventLogging_simple");
511         cattr.setMaxKeySize(100);
512         cattr.setDiskPath("target/test-sandbox/IndexDiskCacheUnitTestCEL");
513         final IndexedDiskCache<String, String> diskCache = new IndexedDiskCache<>(cattr);
514         diskCache.processRemoveAll();
515 
516         final MockCacheEventLogger cacheEventLogger = new MockCacheEventLogger();
517         diskCache.setCacheEventLogger(cacheEventLogger);
518 
519         final ICacheElement<String, String> item = new CacheElement<>("region", "key", "value");
520 
521         // DO WORK
522         diskCache.update(item);
523 
524         SleepUtil.sleepAtLeast(200);
525 
526         // VERIFY
527         assertEquals("Start should have been called.", 1, cacheEventLogger.startICacheEventCalls);
528         assertEquals("End should have been called.", 1, cacheEventLogger.endICacheEventCalls);
529     }
530 
531     /**
532      * Verify event log calls.
533      * <p>
534      *
535      * @throws Exception
536      */
537     public void testGet_EventLogging_simple() throws Exception
538     {
539         // SETUP
540         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
541         cattr.setCacheName("testGet_EventLogging_simple");
542         cattr.setMaxKeySize(100);
543         cattr.setDiskPath("target/test-sandbox/IndexDiskCacheUnitTestCEL");
544         final IndexedDiskCache<String, String> diskCache = new IndexedDiskCache<>(cattr);
545         diskCache.processRemoveAll();
546 
547         final MockCacheEventLogger cacheEventLogger = new MockCacheEventLogger();
548         diskCache.setCacheEventLogger(cacheEventLogger);
549 
550         // DO WORK
551         diskCache.get("key");
552 
553         // VERIFY
554         assertEquals("Start should have been called.", 1, cacheEventLogger.startICacheEventCalls);
555         assertEquals("End should have been called.", 1, cacheEventLogger.endICacheEventCalls);
556     }
557 
558     /**
559      * Verify event log calls.
560      * <p>
561      *
562      * @throws Exception
563      */
564     public void testGetMultiple_EventLogging_simple() throws Exception
565     {
566         // SETUP
567         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
568         cattr.setCacheName("testGetMultiple_EventLogging_simple");
569         cattr.setMaxKeySize(100);
570         cattr.setDiskPath("target/test-sandbox/IndexDiskCacheUnitTestCEL");
571         final IndexedDiskCache<String, String> diskCache = new IndexedDiskCache<>(cattr);
572         diskCache.processRemoveAll();
573 
574         final MockCacheEventLogger cacheEventLogger = new MockCacheEventLogger();
575         diskCache.setCacheEventLogger(cacheEventLogger);
576 
577         final Set<String> keys = new HashSet<>();
578         keys.add("junk");
579 
580         // DO WORK
581         diskCache.getMultiple(keys);
582 
583         // VERIFY
584         // 1 for get multiple and 1 for get.
585         assertEquals("Start should have been called.", 2, cacheEventLogger.startICacheEventCalls);
586         assertEquals("End should have been called.", 2, cacheEventLogger.endICacheEventCalls);
587     }
588 
589     /**
590      * Verify event log calls.
591      * <p>
592      *
593      * @throws Exception
594      */
595     public void testRemove_EventLogging_simple() throws Exception
596     {
597         // SETUP
598         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
599         cattr.setCacheName("testRemoveAll_EventLogging_simple");
600         cattr.setMaxKeySize(100);
601         cattr.setDiskPath("target/test-sandbox/IndexDiskCacheUnitTestCEL");
602         final IndexedDiskCache<String, String> diskCache = new IndexedDiskCache<>(cattr);
603         diskCache.processRemoveAll();
604 
605         final MockCacheEventLogger cacheEventLogger = new MockCacheEventLogger();
606         diskCache.setCacheEventLogger(cacheEventLogger);
607 
608         // DO WORK
609         diskCache.remove("key");
610 
611         // VERIFY
612         assertEquals("Start should have been called.", 1, cacheEventLogger.startICacheEventCalls);
613         assertEquals("End should have been called.", 1, cacheEventLogger.endICacheEventCalls);
614     }
615 
616     /**
617      * Verify event log calls.
618      * <p>
619      *
620      * @throws Exception
621      */
622     public void testRemoveAll_EventLogging_simple() throws Exception
623     {
624         // SETUP
625         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
626         cattr.setCacheName("testRemoveAll_EventLogging_simple");
627         cattr.setMaxKeySize(100);
628         cattr.setDiskPath("target/test-sandbox/IndexDiskCacheUnitTestCEL");
629         final IndexedDiskCache<String, String> diskCache = new IndexedDiskCache<>(cattr);
630         diskCache.processRemoveAll();
631 
632         final MockCacheEventLogger cacheEventLogger = new MockCacheEventLogger();
633         diskCache.setCacheEventLogger(cacheEventLogger);
634 
635         // DO WORK
636         diskCache.remove("key");
637 
638         // VERIFY
639         assertEquals("Start should have been called.", 1, cacheEventLogger.startICacheEventCalls);
640         assertEquals("End should have been called.", 1, cacheEventLogger.endICacheEventCalls);
641     }
642 
643     /**
644      * Test the basic get matching.
645      * <p>
646      *
647      * @throws Exception
648      */
649     public void testPutGetMatching_SmallWait() throws Exception
650     {
651         // SETUP
652         final int items = 200;
653 
654         final String cacheName = "testPutGetMatching_SmallWait";
655         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
656         cattr.setCacheName(cacheName);
657         cattr.setMaxKeySize(100);
658         cattr.setDiskPath("target/test-sandbox/IndexDiskCacheUnitTest");
659         final IndexedDiskCache<String, String> diskCache = new IndexedDiskCache<>(cattr);
660 
661         // DO WORK
662         for (int i = 0; i <= items; i++)
663         {
664             diskCache.update(new CacheElement<>(cacheName, i + ":key", cacheName + " data " + i));
665         }
666         Thread.sleep(500);
667 
668         final Map<String, ICacheElement<String, String>> matchingResults = diskCache.getMatching("1.8.+");
669 
670         // VERIFY
671         assertEquals("Wrong number returned", 10, matchingResults.size());
672         // System.out.println( "matchingResults.keySet() " + matchingResults.keySet() );
673         // System.out.println( "\nAFTER TEST \n" + diskCache.getStats() );
674     }
675 
676     /**
677      * Test the basic get matching. With no wait this will all come from purgatory.
678      * <p>
679      *
680      * @throws Exception
681      */
682     public void testPutGetMatching_NoWait() throws Exception
683     {
684         // SETUP
685         final int items = 200;
686 
687         final String cacheName = "testPutGetMatching_NoWait";
688         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
689         cattr.setCacheName(cacheName);
690         cattr.setMaxKeySize(100);
691         cattr.setDiskPath("target/test-sandbox/IndexDiskCacheUnitTest");
692         final IndexedDiskCache<String, String> diskCache = new IndexedDiskCache<>(cattr);
693 
694         // DO WORK
695         for (int i = 0; i <= items; i++)
696         {
697             diskCache.update(new CacheElement<>(cacheName, i + ":key", cacheName + " data " + i));
698         }
699 
700         final Map<String, ICacheElement<String, String>> matchingResults = diskCache.getMatching("1.8.+");
701 
702         // VERIFY
703         assertEquals("Wrong number returned", 10, matchingResults.size());
704         // System.out.println( "matchingResults.keySet() " + matchingResults.keySet() );
705         // System.out.println( "\nAFTER TEST \n" + diskCache.getStats() );
706     }
707 
708     /**
709      * Verify that the block disk cache can handle utf encoded strings.
710      * <p>
711      *
712      * @throws Exception
713      */
714     public void testUTF8String() throws Exception
715     {
716         String string = "IÒtÎrn‚tiÙn‡lizÊti¯n";
717         final StringBuilder sb = new StringBuilder();
718         sb.append(string);
719         for (int i = 0; i < 4; i++)
720         {
721             sb.append(sb.toString()); // big string
722         }
723         string = sb.toString();
724 
725         // System.out.println( "The string contains " + string.length() + " characters" );
726 
727         final String cacheName = "testUTF8String";
728 
729         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
730         cattr.setCacheName(cacheName);
731         cattr.setMaxKeySize(100);
732         cattr.setDiskPath("target/test-sandbox/IndexDiskCacheUnitTest");
733         final IndexedDiskCache<String, String> diskCache = new IndexedDiskCache<>(cattr);
734 
735         // DO WORK
736         diskCache.update(new CacheElement<>(cacheName, "x", string));
737 
738         // VERIFY
739         assertNotNull(diskCache.get("x"));
740         Thread.sleep(1000);
741         final ICacheElement<String, String> afterElement = diskCache.get("x");
742         assertNotNull(afterElement);
743         // System.out.println( "afterElement = " + afterElement );
744         final String after = afterElement.getVal();
745 
746         assertNotNull(after);
747         assertEquals("wrong string after retrieval", string, after);
748     }
749 
750     /**
751      * Verify that the block disk cache can handle utf encoded strings.
752      * <p>
753      *
754      * @throws Exception
755      */
756     public void testUTF8ByteArray() throws Exception
757     {
758         String string = "IÒtÎrn‚tiÙn‡lizÊti¯n";
759         final StringBuilder sb = new StringBuilder();
760         sb.append(string);
761         for (int i = 0; i < 4; i++)
762         {
763             sb.append(sb.toString()); // big string
764         }
765         string = sb.toString();
766         // System.out.println( "The string contains " + string.length() + " characters" );
767         final byte[] bytes = string.getBytes(StandardCharsets.UTF_8);
768 
769         final String cacheName = "testUTF8ByteArray";
770 
771         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
772         cattr.setCacheName(cacheName);
773         cattr.setMaxKeySize(100);
774         cattr.setDiskPath("target/test-sandbox/IndexDiskCacheUnitTest");
775         final IndexedDiskCache<String, byte[]> diskCache = new IndexedDiskCache<>(cattr);
776 
777         // DO WORK
778         diskCache.update(new CacheElement<>(cacheName, "x", bytes));
779 
780         // VERIFY
781         assertNotNull(diskCache.get("x"));
782         Thread.sleep(1000);
783         final ICacheElement<String, byte[]> afterElement = diskCache.get("x");
784         assertNotNull(afterElement);
785         // System.out.println( "afterElement = " + afterElement );
786         final byte[] after = afterElement.getVal();
787 
788         assertNotNull(after);
789         assertEquals("wrong bytes after retrieval", string, new String(after, StandardCharsets.UTF_8));
790     }
791 
792     /**
793      * Verify the item makes it to disk.
794      * <p>
795      *
796      * @throws IOException
797      */
798     public void testProcessUpdate_Simple() throws IOException
799     {
800         // SETUP
801         final String cacheName = "testProcessUpdate_Simple";
802         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
803         cattr.setCacheName(cacheName);
804         cattr.setMaxKeySize(100);
805         cattr.setDiskPath("target/test-sandbox/IndexDiskCacheUnitTest");
806         final IndexedDiskCache<String, String> diskCache = new IndexedDiskCache<>(cattr);
807 
808         final String key = "myKey";
809         final String value = "myValue";
810         final ICacheElement<String, String> ce = new CacheElement<>(cacheName, key, value);
811 
812         // DO WORK
813         diskCache.processUpdate(ce);
814         final ICacheElement<String, String> result = diskCache.processGet(key);
815 
816         // VERIFY
817         assertNotNull("Should have a result", result);
818         final long fileSize = diskCache.getDataFileSize();
819         assertTrue("File should be greater than 0", fileSize > 0);
820     }
821 
822     /**
823      * Verify the item makes it to disk.
824      * <p>
825      *
826      * @throws IOException
827      */
828     public void testProcessUpdate_SameKeySameSize() throws IOException
829     {
830         // SETUP
831         final String cacheName = "testProcessUpdate_SameKeySameSize";
832         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
833         cattr.setCacheName(cacheName);
834         cattr.setMaxKeySize(100);
835         cattr.setDiskPath("target/test-sandbox/IndexDiskCacheUnitTest");
836         final IndexedDiskCache<String, String> diskCache = new IndexedDiskCache<>(cattr);
837 
838         final String key = "myKey";
839         final String value = "myValue";
840         final ICacheElement<String, String> ce1 = new CacheElement<>(cacheName, key, value);
841 
842         // DO WORK
843         diskCache.processUpdate(ce1);
844         final long fileSize1 = diskCache.getDataFileSize();
845 
846         // DO WORK
847         final ICacheElement<String, String> ce2 = new CacheElement<>(cacheName, key, value);
848         diskCache.processUpdate(ce2);
849         final ICacheElement<String, String> result = diskCache.processGet(key);
850 
851         // VERIFY
852         assertNotNull("Should have a result", result);
853         final long fileSize2 = diskCache.getDataFileSize();
854         assertEquals("File should be the same", fileSize1, fileSize2);
855         final int binSize = diskCache.getRecyleBinSize();
856         assertEquals("Should be nothing in the bin.", 0, binSize);
857     }
858 
859     /**
860      * Verify the item makes it to disk.
861      * <p>
862      *
863      * @throws IOException
864      */
865     public void testProcessUpdate_SameKeySmallerSize() throws IOException
866     {
867         // SETUP
868         final String cacheName = "testProcessUpdate_SameKeySmallerSize";
869         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
870         cattr.setCacheName(cacheName);
871         cattr.setMaxKeySize(100);
872         cattr.setDiskPath("target/test-sandbox/IndexDiskCacheUnitTest");
873         final IndexedDiskCache<String, String> diskCache = new IndexedDiskCache<>(cattr);
874 
875         final String key = "myKey";
876         final String value = "myValue";
877         final String value2 = "myValu";
878         final ICacheElement<String, String> ce1 = new CacheElement<>(cacheName, key, value);
879 
880         // DO WORK
881         diskCache.processUpdate(ce1);
882         final long fileSize1 = diskCache.getDataFileSize();
883 
884         // DO WORK
885         final ICacheElement<String, String> ce2 = new CacheElement<>(cacheName, key, value2);
886         diskCache.processUpdate(ce2);
887         final ICacheElement<String, String> result = diskCache.processGet(key);
888 
889         // VERIFY
890         assertNotNull("Should have a result", result);
891         final long fileSize2 = diskCache.getDataFileSize();
892         assertEquals("File should be the same", fileSize1, fileSize2);
893         final int binSize = diskCache.getRecyleBinSize();
894         assertEquals("Should be nothing in the bin.", 0, binSize);
895     }
896 
897     /**
898      * Verify that the old slot gets in the recycle bin.
899      * <p>
900      *
901      * @throws IOException
902      */
903     public void testProcessUpdate_SameKeyBiggerSize() throws IOException
904     {
905         // SETUP
906         final String cacheName = "testProcessUpdate_SameKeyBiggerSize";
907         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
908         cattr.setCacheName(cacheName);
909         cattr.setMaxKeySize(100);
910         cattr.setDiskPath("target/test-sandbox/IndexDiskCacheUnitTest");
911         final IndexedDiskCache<String, String> diskCache = new IndexedDiskCache<>(cattr);
912 
913         final String key = "myKey";
914         final String value = "myValue";
915         final String value2 = "myValue2";
916         final ICacheElement<String, String> ce1 = new CacheElement<>(cacheName, key, value);
917 
918         // DO WORK
919         diskCache.processUpdate(ce1);
920         final long fileSize1 = diskCache.getDataFileSize();
921 
922         // DO WORK
923         final ICacheElement<String, String> ce2 = new CacheElement<>(cacheName, key, value2);
924         diskCache.processUpdate(ce2);
925         final ICacheElement<String, String> result = diskCache.processGet(key);
926 
927         // VERIFY
928         assertNotNull("Should have a result", result);
929         final long fileSize2 = diskCache.getDataFileSize();
930         assertTrue("File should be greater.", fileSize1 < fileSize2);
931         final int binSize = diskCache.getRecyleBinSize();
932         assertEquals("Should be one in the bin.", 1, binSize);
933     }
934 
935     public void testLoadFromDisk() throws Exception
936     {
937         for (int i = 0; i < 15; i++)
938         { // usually after 2 time it fails
939             oneLoadFromDisk();
940         }
941     }
942 
943     public void oneLoadFromDisk() throws Exception
944     {
945         // initialize object to be stored
946         String string = "IÒtÎrn‚tiÙn‡lizÊti¯n";
947         final StringBuilder sb = new StringBuilder();
948         sb.append(string);
949         for (int i = 0; i < 4; i++)
950         {
951             sb.append(sb.toString()); // big string
952         }
953         string = sb.toString();
954 
955         // initialize cache
956         final String cacheName = "testLoadFromDisk";
957         final IndexedDiskCacheAttributes cattr = getCacheAttributes();
958         cattr.setCacheName(cacheName);
959         cattr.setMaxKeySize(100);
960         cattr.setDiskPath("target/test-sandbox/IndexDiskCacheUnitTest");
961         IndexedDiskCache<String, String> diskCache = new IndexedDiskCache<>(cattr);
962 
963         // DO WORK
964         for (int i = 0; i < 50; i++)
965         {
966             diskCache.update(new CacheElement<>(cacheName, "x" + i, string));
967         }
968         // Thread.sleep(1000);
969         // VERIFY
970         diskCache.dispose();
971         // Thread.sleep(1000);
972 
973         diskCache = new IndexedDiskCache<>(cattr);
974 
975         for (int i = 0; i < 50; i++)
976         {
977             final ICacheElement<String, String> afterElement = diskCache.get("x" + i);
978             assertNotNull("Missing element from cache. Cache size: " + diskCache.getSize() + " element: x" + i, afterElement);
979             assertEquals("wrong string after retrieval", string, afterElement.getVal());
980         }
981     }
982 }