1 package org.apache.jcs.auxiliary.disk.indexed;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.IOException;
23
24 import junit.framework.TestCase;
25
26 import org.apache.jcs.engine.CacheElement;
27 import org.apache.jcs.engine.ElementAttributes;
28 import org.apache.jcs.engine.behavior.ICacheElement;
29 import org.apache.jcs.engine.behavior.IElementAttributes;
30 import org.apache.jcs.engine.control.group.GroupAttrName;
31 import org.apache.jcs.engine.control.group.GroupId;
32
33 /***
34 * Tests for common functionality.
35 * <p>
36 * @author Aaron Smuts
37 */
38 public class IndexDiskCacheUnitTest
39 extends TestCase
40 {
41 /***
42 * Simply verify that we can put items in the disk cache and retrieve them.
43 */
44 public void testSimplePutAndGet()
45 {
46 IndexedDiskCacheAttributes cattr = new IndexedDiskCacheAttributes();
47 cattr.setCacheName( "testSimplePutAndGet" );
48 cattr.setMaxKeySize( 1000 );
49 cattr.setDiskPath( "target/test-sandbox/IndexDiskCacheUnitTest" );
50 IndexedDiskCache disk = new IndexedDiskCache( cattr );
51
52 disk.doRemoveAll();
53
54 int cnt = 999;
55 for ( int i = 0; i < cnt; i++ )
56 {
57 IElementAttributes eAttr = new ElementAttributes();
58 eAttr.setIsSpool( true );
59 ICacheElement element = new CacheElement( "testSimplePutAndGet", "key:" + i, "data:" + i );
60 element.setElementAttributes( eAttr );
61 disk.doUpdate( element );
62 }
63
64 for ( int i = 0; i < cnt; i++ )
65 {
66 ICacheElement element = disk.doGet( "key:" + i );
67 assertNotNull( "Should have recevied an element.", element );
68 assertEquals( "Element is wrong.", "data:" + i, element.getVal() );
69 }
70
71 System.out.println( disk.getStats() );
72 }
73
74 /***
75 * Add some items to the disk cache and then remove them one by one.
76 */
77 public void testRemoveItems()
78 {
79 IndexedDiskCacheAttributes cattr = new IndexedDiskCacheAttributes();
80 cattr.setCacheName( "testRemoveItems" );
81 cattr.setMaxKeySize( 100 );
82 cattr.setDiskPath( "target/test-sandbox/IndexDiskCacheUnitTest" );
83 IndexedDiskCache disk = new IndexedDiskCache( cattr );
84
85 disk.doRemoveAll();
86
87 int cnt = 25;
88 for ( int i = 0; i < cnt; i++ )
89 {
90 IElementAttributes eAttr = new ElementAttributes();
91 eAttr.setIsSpool( true );
92 ICacheElement element = new CacheElement( "testRemoveItems", "key:" + i, "data:" + i );
93 element.setElementAttributes( eAttr );
94 disk.doUpdate( element );
95 }
96
97
98 for ( int i = 0; i < cnt; i++ )
99 {
100 disk.remove( "key:" + i );
101 ICacheElement element = disk.doGet( "key:" + i );
102 assertNull( "Should not have recevied an element.", element );
103 }
104 }
105
106 /***
107 * Verify that we don't override the largest item.
108 */
109 public void testRecycleBin()
110 {
111 IndexedDiskCacheAttributes cattr = new IndexedDiskCacheAttributes();
112 cattr.setCacheName( "testRemoveItems" );
113 cattr.setMaxRecycleBinSize( 2 );
114 cattr.setOptimizeAtRemoveCount( 7 );
115 cattr.setMaxKeySize( 5 );
116 cattr.setMaxPurgatorySize( 0 );
117 cattr.setDiskPath( "target/test-sandbox/BreakIndexTest" );
118 IndexedDiskCache disk = new IndexedDiskCache( cattr );
119
120 String[] test = { "a", "bb", "ccc", "dddd", "eeeee", "ffffff", "ggggggg", "hhhhhhhhh", "iiiiiiiiii" };
121 String[] expect = { null, "bb", "ccc", null, null, "ffffff", null, "hhhhhhhhh", "iiiiiiiiii" };
122
123 System.out.println( "------------------------- testRecycleBin " );
124
125 for ( int i = 0; i < 6; i++ )
126 {
127 ICacheElement element = new CacheElement( "testRecycleBin", "key:" + test[i], test[i] );
128 System.out.println( "About to add " + "key:" + test[i] + " i = " + i );
129 disk.doUpdate( element );
130 }
131
132 for ( int i = 3; i < 5; i++ )
133 {
134 System.out.println( "About to remove " + "key:" + test[i] + " i = " + i );
135 disk.remove( "key:" + test[i] );
136 }
137
138
139
140 for ( int i = 7; i < 9; i++ )
141 {
142 ICacheElement element = new CacheElement( "testRecycleBin", "key:" + test[i], test[i] );
143 System.out.println( "About to add " + "key:" + test[i] + " i = " + i );
144 disk.doUpdate( element );
145 }
146
147 try
148 {
149 for ( int i = 0; i < 9; i++ )
150 {
151 ICacheElement element = disk.get( "key:" + test[i] );
152 if ( element != null )
153 {
154 System.out.println( "element = " + element.getVal() );
155 }
156 else
157 {
158 System.out.println( "null --" + "key:" + test[i] );
159 }
160
161 String expectedValue = expect[i];
162 if ( expectedValue == null )
163 {
164 assertNull( "Expected a null element", element );
165 }
166 else
167 {
168 assertNotNull( "The element for key [" + "key:" + test[i] + "] should not be null. i = " + i,
169 element );
170 assertEquals( "Elements contents do not match expected", element.getVal(), expectedValue );
171 }
172 }
173 }
174 catch ( Exception e )
175 {
176 e.printStackTrace();
177 fail( "Should not get an exception: " + e.toString() );
178 }
179
180 disk.removeAll();
181 }
182
183 /***
184 * Verify that the overlap check returns true when there are no overlaps.
185 */
186 public void testCheckForDedOverlaps_noOverlap()
187 {
188
189 IndexedDiskCacheAttributes cattr = new IndexedDiskCacheAttributes();
190 cattr.setCacheName( "testCheckForDedOverlaps_noOverlap" );
191 cattr.setDiskPath( "target/test-sandbox/UnitTest" );
192 IndexedDiskCache disk = new IndexedDiskCache( cattr );
193
194 int numDescriptors = 5;
195 int pos = 0;
196 IndexedDiskElementDescriptor[] sortedDescriptors = new IndexedDiskElementDescriptor[numDescriptors];
197 for ( int i = 0; i < numDescriptors; i++ )
198 {
199 IndexedDiskElementDescriptor descriptor = new IndexedDiskElementDescriptor( pos, i * 2 );
200 pos = pos + ( i * 2 ) + IndexedDisk.RECORD_HEADER;
201 sortedDescriptors[i] = descriptor;
202 }
203
204
205 boolean result = disk.checkForDedOverlaps( sortedDescriptors );
206
207
208 assertTrue( "There should be no overlap. it should be ok", result );
209 }
210
211 /***
212 * Verify that the overlap check returns false when there are overlaps.
213 */
214 public void testCheckForDedOverlaps_overlaps()
215 {
216
217 IndexedDiskCacheAttributes cattr = new IndexedDiskCacheAttributes();
218 cattr.setCacheName( "testCheckForDedOverlaps_overlaps" );
219 cattr.setDiskPath( "target/test-sandbox/UnitTest" );
220 IndexedDiskCache disk = new IndexedDiskCache( cattr );
221
222 int numDescriptors = 5;
223 int pos = 0;
224 IndexedDiskElementDescriptor[] sortedDescriptors = new IndexedDiskElementDescriptor[numDescriptors];
225 for ( int i = 0; i < numDescriptors; i++ )
226 {
227 IndexedDiskElementDescriptor descriptor = new IndexedDiskElementDescriptor( pos, i * 2 );
228
229 pos = pos + ( i * 2 );
230 sortedDescriptors[i] = descriptor;
231 }
232
233
234 boolean result = disk.checkForDedOverlaps( sortedDescriptors );
235
236
237 assertFalse( "There should be overlaps. it should be not ok", result );
238 }
239
240 /***
241 * Verify that the file size is as expected.
242 * @throws IOException
243 * @throws InterruptedException
244 */
245 public void testFileSize()
246 throws IOException, InterruptedException
247 {
248
249 IndexedDiskCacheAttributes cattr = new IndexedDiskCacheAttributes();
250 cattr.setCacheName( "testFileSize" );
251 cattr.setDiskPath( "target/test-sandbox/UnitTest" );
252 IndexedDiskCache disk = new IndexedDiskCache( cattr );
253
254 int numberToInsert = 20;
255 int bytes = 24;
256 ICacheElement[] elements = DiskTestObjectUtil.createCacheElementsWithTestObjects( numberToInsert, bytes, cattr
257 .getCacheName() );
258
259 for ( int i = 0; i < elements.length; i++ )
260 {
261 disk.doUpdate( elements[i] );
262 }
263
264 Thread.yield();
265 Thread.sleep( 100 );
266 Thread.yield();
267
268 long expectedSize = DiskTestObjectUtil.totalSize( elements, numberToInsert );
269 long resultSize = disk.getDataFileSize();
270
271 System.out.println( "testFileSize stats " + disk.getStats() );
272
273 assertEquals( "Wrong file size", expectedSize, resultSize );
274 }
275
276 /***
277 * Verify that items are added to the recyle bin on removal.
278 * <p>
279 * @throws IOException
280 * @throws InterruptedException
281 */
282 public void testRecyleBinSize()
283 throws IOException, InterruptedException
284 {
285
286 int numberToInsert = 20;
287
288 IndexedDiskCacheAttributes cattr = new IndexedDiskCacheAttributes();
289 cattr.setCacheName( "testRecyleBinSize" );
290 cattr.setDiskPath( "target/test-sandbox/UnitTest" );
291 cattr.setMaxRecycleBinSize( numberToInsert );
292 cattr.setOptimizeAtRemoveCount( numberToInsert );
293 cattr.setMaxKeySize( numberToInsert * 2 );
294 cattr.setMaxPurgatorySize( numberToInsert );
295 IndexedDiskCache disk = new IndexedDiskCache( cattr );
296
297 int bytes = 24;
298 ICacheElement[] elements = DiskTestObjectUtil.createCacheElementsWithTestObjects( numberToInsert, bytes, cattr
299 .getCacheName() );
300
301 for ( int i = 0; i < elements.length; i++ )
302 {
303 disk.doUpdate( elements[i] );
304 }
305
306 Thread.yield();
307 Thread.sleep( 100 );
308 Thread.yield();
309
310
311 int numberToRemove = elements.length / 2;
312 for ( int i = 0; i < numberToRemove; i++ )
313 {
314 disk.doRemove( elements[i].getKey() );
315 }
316
317
318 assertEquals( "The recycle bin should have the number removed.", numberToRemove, disk.getRecyleBinSize() );
319 }
320
321 /***
322 * Verify that items of the same size use recyle bin spots. Setup the receyle bin by removing
323 * some items. Add some of the same size. Verify that the recyle count is the number added.
324 * <p>
325 * @throws IOException
326 * @throws InterruptedException
327 */
328 public void testRecyleBinUsage()
329 throws IOException, InterruptedException
330 {
331
332 int numberToInsert = 20;
333
334 IndexedDiskCacheAttributes cattr = new IndexedDiskCacheAttributes();
335 cattr.setCacheName( "testRecyleBinUsage" );
336 cattr.setDiskPath( "target/test-sandbox/UnitTest" );
337 cattr.setMaxRecycleBinSize( numberToInsert );
338 cattr.setOptimizeAtRemoveCount( numberToInsert );
339 cattr.setMaxKeySize( numberToInsert * 2 );
340 cattr.setMaxPurgatorySize( numberToInsert );
341 IndexedDiskCache disk = new IndexedDiskCache( cattr );
342
343
344 int bytes = 24;
345 ICacheElement[] elements = DiskTestObjectUtil.createCacheElementsWithTestObjects( numberToInsert, bytes, cattr
346 .getCacheName() );
347
348
349 for ( int i = 0; i < elements.length; i++ )
350 {
351 disk.doUpdate( elements[i] );
352 }
353
354 Thread.yield();
355 Thread.sleep( 100 );
356 Thread.yield();
357
358
359 int numberToRemove = elements.length / 2;
360 for ( int i = 0; i < numberToRemove; i++ )
361 {
362 disk.doRemove( elements[i].getKey() );
363 }
364
365
366 assertEquals( "The recycle bin should have the number removed.", numberToRemove, disk.getRecyleBinSize() );
367
368
369 int numberToAdd = numberToRemove / 2;
370 for ( int i = 0; i < numberToAdd; i++ )
371 {
372 disk.doUpdate( elements[i] );
373 }
374
375
376 assertEquals( "The recycle bin should have the number removed." + disk.getStats(), numberToAdd, disk
377 .getRecyleCount() );
378 }
379
380 /***
381 * Verify that the data size is as expected after a remove and after a put that should use the
382 * spots.
383 * <p>
384 * @throws IOException
385 * @throws InterruptedException
386 */
387 public void testBytesFreeSize()
388 throws IOException, InterruptedException
389 {
390
391 IndexedDiskCacheAttributes cattr = new IndexedDiskCacheAttributes();
392 cattr.setCacheName( "testBytesFreeSize" );
393 cattr.setDiskPath( "target/test-sandbox/UnitTest" );
394 IndexedDiskCache disk = new IndexedDiskCache( cattr );
395
396 int numberToInsert = 20;
397 int bytes = 24;
398 ICacheElement[] elements = DiskTestObjectUtil.createCacheElementsWithTestObjects( numberToInsert, bytes, cattr
399 .getCacheName() );
400
401 for ( int i = 0; i < elements.length; i++ )
402 {
403 disk.doUpdate( elements[i] );
404 }
405
406 Thread.yield();
407 Thread.sleep( 100 );
408 Thread.yield();
409
410
411 int numberToRemove = elements.length / 2;
412 for ( int i = 0; i < numberToRemove; i++ )
413 {
414 disk.doRemove( elements[i].getKey() );
415 }
416
417 long expectedSize = DiskTestObjectUtil.totalSize( elements, numberToRemove );
418 long resultSize = disk.getBytesFree();
419
420 System.out.println( "testBytesFreeSize stats " + disk.getStats() );
421
422 assertEquals( "Wrong bytes free size" + disk.getStats(), expectedSize, resultSize );
423
424
425 int numberToAdd = numberToRemove / 2;
426 for ( int i = 0; i < numberToAdd; i++ )
427 {
428 disk.doUpdate( elements[i] );
429 }
430
431 long expectedSize2 = DiskTestObjectUtil.totalSize( elements, numberToAdd );
432 long resultSize2 = disk.getBytesFree();
433 assertEquals( "Wrong bytes free size" + disk.getStats(), expectedSize2, resultSize2 );
434 }
435
436 /***
437 * Add some items to the disk cache and then remove them one by one.
438 */
439 public void testRemove_PartialKey()
440 {
441 IndexedDiskCacheAttributes cattr = new IndexedDiskCacheAttributes();
442 cattr.setCacheName( "testRemove_PartialKey" );
443 cattr.setMaxKeySize( 100 );
444 cattr.setDiskPath( "target/test-sandbox/IndexDiskCacheUnitTest" );
445 IndexedDiskCache disk = new IndexedDiskCache( cattr );
446
447 disk.doRemoveAll();
448
449 int cnt = 25;
450 for ( int i = 0; i < cnt; i++ )
451 {
452 IElementAttributes eAttr = new ElementAttributes();
453 eAttr.setIsSpool( true );
454 ICacheElement element = new CacheElement( "testRemove_PartialKey", i + ":key", "data:" + i );
455 element.setElementAttributes( eAttr );
456 disk.doUpdate( element );
457 }
458
459
460 for ( int i = 0; i < cnt; i++ )
461 {
462 ICacheElement element = disk.doGet( i + ":key" );
463 assertNotNull( "Shoulds have recevied an element.", element );
464 }
465
466
467 for ( int i = 0; i < cnt; i++ )
468 {
469 disk.remove( i + ":" );
470 ICacheElement element = disk.doGet( i + ":key" );
471 assertNull( "Should not have recevied an element.", element );
472 }
473 }
474
475 /***
476 * Verify that group members are removed if we call remove with a group.
477 */
478 public void testRemove_Group()
479 {
480
481 IndexedDiskCacheAttributes cattr = new IndexedDiskCacheAttributes();
482 cattr.setCacheName( "testRemove_Group" );
483 cattr.setMaxKeySize( 100 );
484 cattr.setDiskPath( "target/test-sandbox/IndexDiskCacheUnitTest" );
485 IndexedDiskCache disk = new IndexedDiskCache( cattr );
486
487 disk.doRemoveAll();
488
489 String cacheName = "testRemove_Group_Region";
490 String groupName = "testRemove_Group";
491
492 int cnt = 25;
493 for ( int i = 0; i < cnt; i++ )
494 {
495 GroupAttrName groupAttrName = getGroupAttrName( cacheName, groupName, i + ":key" );
496
497 CacheElement element = new CacheElement( cacheName, groupAttrName, "data:" + i );
498
499 IElementAttributes eAttr = new ElementAttributes();
500 eAttr.setIsSpool( true );
501 element.setElementAttributes( eAttr );
502
503 disk.doUpdate( element );
504 }
505
506
507 for ( int i = 0; i < cnt; i++ )
508 {
509 GroupAttrName groupAttrName = getGroupAttrName( cacheName, groupName, i + ":key" );
510 ICacheElement element = disk.doGet( groupAttrName );
511 assertNotNull( "Should have recevied an element.", element );
512 }
513
514
515
516 GroupId gid = new GroupId( cacheName, groupName );
517 disk.remove( gid );
518
519 for ( int i = 0; i < cnt; i++ )
520 {
521 GroupAttrName groupAttrName = getGroupAttrName( cacheName, groupName, i + ":key" );
522 ICacheElement element = disk.doGet( groupAttrName );
523
524
525 assertNull( "Should not have recevied an element.", element );
526 }
527
528 }
529
530 /***
531 * Internal method used for group functionality.
532 * <p>
533 * @param cacheName
534 * @param group
535 * @param name
536 * @return GroupAttrName
537 */
538 private GroupAttrName getGroupAttrName( String cacheName, String group, Object name )
539 {
540 GroupId gid = new GroupId( cacheName, group );
541 return new GroupAttrName( gid, name );
542 }
543 }