View Javadoc
1   package org.apache.commons.jcs.auxiliary.disk.block;
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.File;
23  import java.io.IOException;
24  import java.io.Serializable;
25  import java.util.Map;
26  
27  import junit.framework.TestCase;
28  
29  import org.apache.commons.jcs.engine.CacheElement;
30  import org.apache.commons.jcs.engine.ElementAttributes;
31  import org.apache.commons.jcs.engine.behavior.ICacheElement;
32  import org.apache.commons.jcs.engine.behavior.IElementAttributes;
33  import org.apache.commons.jcs.engine.control.group.GroupAttrName;
34  import org.apache.commons.jcs.engine.control.group.GroupId;
35  import org.apache.commons.jcs.utils.serialization.StandardSerializer;
36  
37  /** Unit tests for the Block Disk Cache */
38  public abstract class BlockDiskCacheUnitTestAbstract extends TestCase
39  {
40      public abstract BlockDiskCacheAttributes getCacheAttributes();
41  
42      public void testPutGetMatching_SmallWait() throws Exception
43      {
44          // SETUP
45          int items = 200;
46  
47          String cacheName = "testPutGetMatching_SmallWait";
48          BlockDiskCacheAttributes cattr = getCacheAttributes();
49          cattr.setCacheName(cacheName);
50          cattr.setMaxKeySize(100);
51          cattr.setDiskPath("target/test-sandbox/BlockDiskCacheUnitTest");
52          BlockDiskCache<String, String> diskCache = new BlockDiskCache<String, String>(cattr);
53  
54          // DO WORK
55          for (int i = 0; i <= items; i++)
56          {
57              diskCache.update(new CacheElement<String, String>(cacheName, i + ":key", cacheName + " data " + i));
58          }
59          Thread.sleep(500);
60  
61          Map<String, ICacheElement<String, String>> matchingResults = diskCache.getMatching("1.8.+");
62  
63          // VERIFY
64          assertEquals("Wrong number returned", 10, matchingResults.size());
65          // System.out.println( "matchingResults.keySet() " + matchingResults.keySet() );
66          // System.out.println( "\nAFTER TEST \n" + diskCache.getStats() );
67      }
68  
69      /**
70       * Test the basic get matching. With no wait this will all come from purgatory.
71       * <p>
72       *
73       * @throws Exception
74       */
75      public void testPutGetMatching_NoWait() throws Exception
76      {
77          // SETUP
78          int items = 200;
79  
80          String cacheName = "testPutGetMatching_NoWait";
81          BlockDiskCacheAttributes cattr = getCacheAttributes();
82          cattr.setCacheName(cacheName);
83          cattr.setMaxKeySize(100);
84          cattr.setDiskPath("target/test-sandbox/BlockDiskCacheUnitTest");
85          BlockDiskCache<String, String> diskCache = new BlockDiskCache<String, String>(cattr);
86  
87          // DO WORK
88          for (int i = 0; i <= items; i++)
89          {
90              diskCache.update(new CacheElement<String, String>(cacheName, i + ":key", cacheName + " data " + i));
91          }
92  
93          Map<String, ICacheElement<String, String>> matchingResults = diskCache.getMatching("1.8.+");
94  
95          // VERIFY
96          assertEquals("Wrong number returned", 10, matchingResults.size());
97          // System.out.println( "matchingResults.keySet() " + matchingResults.keySet() );
98          // System.out.println( "\nAFTER TEST \n" + diskCache.getStats() );
99      }
100 
101     /**
102      * Verify that the block disk cache can handle a big string.
103      * <p>
104      *
105      * @throws Exception
106      */
107     public void testChunk_BigString() throws Exception
108     {
109         String string = "This is my big string ABCDEFGH";
110         StringBuilder sb = new StringBuilder();
111         sb.append(string);
112         for (int i = 0; i < 4; i++)
113         {
114             sb.append("|" + i + ":" + sb.toString()); // big string
115         }
116         string = sb.toString();
117 
118         StandardSerializer elementSerializer = new StandardSerializer();
119         byte[] data = elementSerializer.serialize(string);
120 
121         File file = new File("target/test-sandbox/BlockDiskCacheUnitTest/testChunk_BigString.data");
122 
123         BlockDisk blockDisk = new BlockDisk(file, 200, elementSerializer);
124 
125         int numBlocksNeeded = blockDisk.calculateTheNumberOfBlocksNeeded(data);
126         // System.out.println( numBlocksNeeded );
127 
128         // get the individual sub arrays.
129         byte[][] chunks = blockDisk.getBlockChunks(data, numBlocksNeeded);
130 
131         byte[] resultData = new byte[0];
132 
133         for (short i = 0; i < chunks.length; i++)
134         {
135             byte[] chunk = chunks[i];
136             byte[] newTotal = new byte[data.length + chunk.length];
137             // copy data into the new array
138             System.arraycopy(data, 0, newTotal, 0, data.length);
139             // copy the chunk into the new array
140             System.arraycopy(chunk, 0, newTotal, data.length, chunk.length);
141             // swap the new and old.
142             resultData = newTotal;
143         }
144 
145         Serializable result = elementSerializer.deSerialize(resultData, null);
146         // System.out.println( result );
147         assertEquals("wrong string after retrieval", string, result);
148     }
149 
150     /**
151      * Verify that the block disk cache can handle a big string.
152      * <p>
153      *
154      * @throws Exception
155      */
156     public void testPutGet_BigString() throws Exception
157     {
158         String string = "This is my big string ABCDEFGH";
159         StringBuilder sb = new StringBuilder();
160         sb.append(string);
161         for (int i = 0; i < 4; i++)
162         {
163             sb.append(" " + i + sb.toString()); // big string
164         }
165         string = sb.toString();
166 
167         String cacheName = "testPutGet_BigString";
168 
169         BlockDiskCacheAttributes cattr = getCacheAttributes();
170         cattr.setCacheName(cacheName);
171         cattr.setMaxKeySize(100);
172         cattr.setBlockSizeBytes(200);
173         cattr.setDiskPath("target/test-sandbox/BlockDiskCacheUnitTest");
174         BlockDiskCache<String, String> diskCache = new BlockDiskCache<String, String>(cattr);
175 
176         // DO WORK
177         diskCache.update(new CacheElement<String, String>(cacheName, "x", string));
178 
179         // VERIFY
180         assertNotNull(diskCache.get("x"));
181         Thread.sleep(1000);
182         ICacheElement<String, String> afterElement = diskCache.get("x");
183         assertNotNull(afterElement);
184         // System.out.println( "afterElement = " + afterElement );
185         String after = afterElement.getVal();
186 
187         assertNotNull(after);
188         assertEquals("wrong string after retrieval", string, after);
189     }
190 
191     /**
192      * Verify that the block disk cache can handle utf encoded strings.
193      * <p>
194      *
195      * @throws Exception
196      */
197     public void testUTF8String() throws Exception
198     {
199         String string = "IÒtÎrn‚tiÙn‡lizÊti¯n";
200         StringBuilder sb = new StringBuilder();
201         sb.append(string);
202         for (int i = 0; i < 4; i++)
203         {
204             sb.append(sb.toString()); // big string
205         }
206         string = sb.toString();
207 
208         // System.out.println( "The string contains " + string.length() + " characters" );
209 
210         String cacheName = "testUTF8String";
211 
212         BlockDiskCacheAttributes cattr = getCacheAttributes();
213         cattr.setCacheName(cacheName);
214         cattr.setMaxKeySize(100);
215         cattr.setBlockSizeBytes(200);
216         cattr.setDiskPath("target/test-sandbox/BlockDiskCacheUnitTest");
217         BlockDiskCache<String, String> diskCache = new BlockDiskCache<String, String>(cattr);
218 
219         // DO WORK
220         diskCache.update(new CacheElement<String, String>(cacheName, "x", string));
221 
222         // VERIFY
223         assertNotNull(diskCache.get("x"));
224         Thread.sleep(1000);
225         ICacheElement<String, String> afterElement = diskCache.get("x");
226         assertNotNull(afterElement);
227         // System.out.println( "afterElement = " + afterElement );
228         String after = afterElement.getVal();
229 
230         assertNotNull(after);
231         assertEquals("wrong string after retrieval", string, after);
232     }
233 
234     /**
235      * Verify that the block disk cache can handle utf encoded strings.
236      * <p>
237      *
238      * @throws Exception
239      */
240     public void testUTF8ByteArray() throws Exception
241     {
242         String string = "IÒtÎrn‚tiÙn‡lizÊti¯n";
243         StringBuilder sb = new StringBuilder();
244         sb.append(string);
245         for (int i = 0; i < 4; i++)
246         {
247             sb.append(sb.toString()); // big string
248         }
249         string = sb.toString();
250         // System.out.println( "The string contains " + string.length() + " characters" );
251         String UTF8 = "UTF-8";
252         byte[] bytes = string.getBytes(UTF8);
253 
254         String cacheName = "testUTF8ByteArray";
255 
256         BlockDiskCacheAttributes cattr = getCacheAttributes();
257         cattr.setCacheName(cacheName);
258         cattr.setMaxKeySize(100);
259         cattr.setBlockSizeBytes(200);
260         cattr.setDiskPath("target/test-sandbox/BlockDiskCacheUnitTest");
261         BlockDiskCache<String, byte[]> diskCache = new BlockDiskCache<String, byte[]>(cattr);
262 
263         // DO WORK
264         diskCache.update(new CacheElement<String, byte[]>(cacheName, "x", bytes));
265 
266         // VERIFY
267         assertNotNull(diskCache.get("x"));
268         Thread.sleep(1000);
269         ICacheElement<String, byte[]> afterElement = diskCache.get("x");
270         assertNotNull(afterElement);
271         // System.out.println( "afterElement = " + afterElement );
272         byte[] after = afterElement.getVal();
273 
274         assertNotNull(after);
275         assertEquals("wrong bytes after retrieval", bytes.length, after.length);
276         // assertEquals( "wrong bytes after retrieval", bytes, after );
277         // assertEquals( "wrong bytes after retrieval", string, new String( after, UTF8 ) );
278 
279     }
280 
281     /**
282      * Verify that the block disk cache can handle utf encoded strings.
283      * <p>
284      *
285      * @throws Exception
286      */
287     public void testUTF8StringAndBytes() throws Exception
288     {
289         X before = new X();
290         String string = "IÒtÎrn‚tiÙn‡lizÊti¯n";
291         StringBuilder sb = new StringBuilder();
292         sb.append(string);
293         for (int i = 0; i < 4; i++)
294         {
295             sb.append(sb.toString()); // big string
296         }
297         string = sb.toString();
298         // System.out.println( "The string contains " + string.length() + " characters" );
299         String UTF8 = "UTF-8";
300         before.string = string;
301         before.bytes = string.getBytes(UTF8);
302 
303         String cacheName = "testUTF8StringAndBytes";
304 
305         BlockDiskCacheAttributes cattr = getCacheAttributes();
306         cattr.setCacheName(cacheName);
307         cattr.setMaxKeySize(100);
308         cattr.setBlockSizeBytes(500);
309         cattr.setDiskPath("target/test-sandbox/BlockDiskCacheUnitTest");
310         BlockDiskCache<String, X> diskCache = new BlockDiskCache<String, X>(cattr);
311 
312         // DO WORK
313         diskCache.update(new CacheElement<String, X>(cacheName, "x", before));
314 
315         // VERIFY
316         assertNotNull(diskCache.get("x"));
317         Thread.sleep(1000);
318         ICacheElement<String, X> afterElement = diskCache.get("x");
319         // System.out.println( "afterElement = " + afterElement );
320         X after = (afterElement.getVal());
321 
322         assertNotNull(after);
323         assertEquals("wrong string after retrieval", string, after.string);
324         assertEquals("wrong bytes after retrieval", string, new String(after.bytes, UTF8));
325 
326     }
327 
328     public void testLoadFromDisk() throws Exception
329     {
330         for (int i = 0; i < 20; i++)
331         { // usually after 2 time it fails
332             oneLoadFromDisk();
333         }
334     }
335 
336     public void testAppendToDisk() throws Exception
337     {
338         String cacheName = "testAppendToDisk";
339         BlockDiskCacheAttributes cattr = getCacheAttributes();
340         cattr.setCacheName(cacheName);
341         cattr.setMaxKeySize(100);
342         cattr.setBlockSizeBytes(500);
343         cattr.setDiskPath("target/test-sandbox/BlockDiskCacheUnitTest");
344         BlockDiskCache<String, X> diskCache = new BlockDiskCache<String, X>(cattr);
345         diskCache.removeAll();
346         X value1 = new X();
347         value1.string = "1234567890";
348         X value2 = new X();
349         value2.string = "0987654321";
350         diskCache.update(new CacheElement<String, X>(cacheName, "1", value1));
351         diskCache.dispose();
352         diskCache = new BlockDiskCache<String, X>(cattr);
353         diskCache.update(new CacheElement<String, X>(cacheName, "2", value2));
354         diskCache.dispose();
355         diskCache = new BlockDiskCache<String, X>(cattr);
356         assertTrue(diskCache.verifyDisk());
357         assertEquals(2, diskCache.getKeySet().size());
358         assertEquals(value1.string, diskCache.get("1").getVal().string);
359         assertEquals(value2.string, diskCache.get("2").getVal().string);
360     }
361 
362     public void oneLoadFromDisk() throws Exception
363     {
364         // initialize object to be stored
365         X before = new X();
366         String string = "IÒtÎrn‚tiÙn‡lizÊti¯n";
367         StringBuilder sb = new StringBuilder();
368         sb.append(string);
369         for (int i = 0; i < 4; i++)
370         {
371             sb.append(sb.toString()); // big string
372         }
373         string = sb.toString();
374         String UTF8 = "UTF-8";
375         before.string = string;
376         before.bytes = string.getBytes(UTF8);
377 
378         // initialize cache
379         String cacheName = "testLoadFromDisk";
380         BlockDiskCacheAttributes cattr = getCacheAttributes();
381         cattr.setCacheName(cacheName);
382         cattr.setMaxKeySize(100);
383         cattr.setBlockSizeBytes(500);
384         cattr.setDiskPath("target/test-sandbox/BlockDiskCacheUnitTest");
385         BlockDiskCache<String, X> diskCache = new BlockDiskCache<String, X>(cattr);
386 
387         // DO WORK
388         for (int i = 0; i < 50; i++)
389         {
390             diskCache.update(new CacheElement<String, X>(cacheName, "x" + i, before));
391         }
392         diskCache.dispose();
393 
394         // VERIFY
395         diskCache = new BlockDiskCache<String, X>(cattr);
396 
397         for (int i = 0; i < 50; i++)
398         {
399             ICacheElement<String, X> afterElement = diskCache.get("x" + i);
400             assertNotNull("Missing element from cache. Cache size: " + diskCache.getSize() + " element: x" + i, afterElement);
401             X after = (afterElement.getVal());
402 
403             assertNotNull(after);
404             assertEquals("wrong string after retrieval", string, after.string);
405             assertEquals("wrong bytes after retrieval", string, new String(after.bytes, UTF8));
406         }
407 
408         diskCache.dispose();
409     }
410 
411     /**
412      * Add some items to the disk cache and then remove them one by one.
413      *
414      * @throws IOException
415      */
416     public void testRemoveItems() throws IOException
417     {
418         BlockDiskCacheAttributes cattr = getCacheAttributes();
419         cattr.setCacheName("testRemoveItems");
420         cattr.setMaxKeySize(100);
421         cattr.setDiskPath("target/test-sandbox/BlockDiskCacheUnitTest");
422         BlockDiskCache<String, String> disk = new BlockDiskCache<String, String>(cattr);
423 
424         disk.processRemoveAll();
425 
426         int cnt = 25;
427         for (int i = 0; i < cnt; i++)
428         {
429             IElementAttributes eAttr = new ElementAttributes();
430             eAttr.setIsSpool(true);
431             ICacheElement<String, String> element = new CacheElement<String, String>("testRemoveItems", "key:" + i, "data:" + i);
432             element.setElementAttributes(eAttr);
433             disk.processUpdate(element);
434         }
435 
436         // remove each
437         for (int i = 0; i < cnt; i++)
438         {
439             disk.remove("key:" + i);
440             ICacheElement<String, String> element = disk.processGet("key:" + i);
441             assertNull("Should not have received an element.", element);
442         }
443     }
444 
445     /**
446      * Add some items to the disk cache and then remove them one by one.
447      * <p>
448      *
449      * @throws IOException
450      */
451     public void testRemove_PartialKey() throws IOException
452     {
453         BlockDiskCacheAttributes cattr = getCacheAttributes();
454         cattr.setCacheName("testRemove_PartialKey");
455         cattr.setMaxKeySize(100);
456         cattr.setDiskPath("target/test-sandbox/BlockDiskCacheUnitTest");
457         BlockDiskCache<String, String> disk = new BlockDiskCache<String, String>(cattr);
458 
459         disk.processRemoveAll();
460 
461         int cnt = 25;
462         for (int i = 0; i < cnt; i++)
463         {
464             IElementAttributes eAttr = new ElementAttributes();
465             eAttr.setIsSpool(true);
466             ICacheElement<String, String> element = new CacheElement<String, String>("testRemove_PartialKey", i + ":key", "data:"
467                 + i);
468             element.setElementAttributes(eAttr);
469             disk.processUpdate(element);
470         }
471 
472         // verify each
473         for (int i = 0; i < cnt; i++)
474         {
475             ICacheElement<String, String> element = disk.processGet(i + ":key");
476             assertNotNull("Shoulds have received an element.", element);
477         }
478 
479         // remove each
480         for (int i = 0; i < cnt; i++)
481         {
482             disk.remove(i + ":");
483             ICacheElement<String, String> element = disk.processGet(i + ":key");
484             assertNull("Should not have received an element.", element);
485         }
486     }
487 
488 
489     /**
490      * Verify that group members are removed if we call remove with a group.
491      *
492      * @throws IOException
493      */
494     public void testRemove_Group() throws IOException
495     {
496         // SETUP
497         BlockDiskCacheAttributes cattr = getCacheAttributes();
498         cattr.setCacheName("testRemove_Group");
499         cattr.setMaxKeySize(100);
500         cattr.setDiskPath("target/test-sandbox/BlockDiskCacheUnitTest");
501         BlockDiskCache<GroupAttrName<String>, String> disk = new BlockDiskCache<GroupAttrName<String>, String>(cattr);
502 
503         disk.processRemoveAll();
504 
505         String cacheName = "testRemove_Group_Region";
506         String groupName = "testRemove_Group";
507 
508         int cnt = 25;
509         for (int i = 0; i < cnt; i++)
510         {
511             GroupAttrName<String> groupAttrName = getGroupAttrName(cacheName, groupName, i + ":key");
512             CacheElement<GroupAttrName<String>, String> element = new CacheElement<GroupAttrName<String>, String>(cacheName,
513                 groupAttrName, "data:" + i);
514 
515             IElementAttributes eAttr = new ElementAttributes();
516             eAttr.setIsSpool(true);
517             element.setElementAttributes(eAttr);
518 
519             disk.processUpdate(element);
520         }
521 
522         // verify each
523         for (int i = 0; i < cnt; i++)
524         {
525             GroupAttrName<String> groupAttrName = getGroupAttrName(cacheName, groupName, i + ":key");
526             ICacheElement<GroupAttrName<String>, String> element = disk.processGet(groupAttrName);
527             assertNotNull("Should have received an element.", element);
528         }
529 
530         // DO WORK
531         // remove the group
532         disk.remove(getGroupAttrName(cacheName, groupName, null));
533 
534         for (int i = 0; i < cnt; i++)
535         {
536             GroupAttrName<String> groupAttrName = getGroupAttrName(cacheName, groupName, i + ":key");
537             ICacheElement<GroupAttrName<String>, String> element = disk.processGet(groupAttrName);
538 
539             // VERIFY
540             assertNull("Should not have received an element.", element);
541         }
542 
543     }
544 
545     /**
546      * Internal method used for group functionality.
547      * <p>
548      *
549      * @param cacheName
550      * @param group
551      * @param name
552      * @return GroupAttrName
553      */
554     private GroupAttrName<String> getGroupAttrName(String cacheName, String group, String name)
555     {
556         GroupId gid = new GroupId(cacheName, group);
557         return new GroupAttrName<String>(gid, name);
558     }
559 
560     /** Holder for a string and byte array. */
561     static class X implements Serializable
562     {
563         /** ignore */
564         private static final long serialVersionUID = 1L;
565 
566         /** Test string */
567         String string;
568 
569         /*** test byte array. */
570         byte[] bytes;
571     }
572 }