1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.mavibot.btree;
21
22
23 import static org.junit.Assert.assertEquals;
24 import static org.junit.Assert.assertFalse;
25 import static org.junit.Assert.assertNotNull;
26 import static org.junit.Assert.assertNull;
27 import static org.junit.Assert.assertTrue;
28 import static org.junit.Assert.fail;
29
30 import java.io.IOException;
31 import java.util.NoSuchElementException;
32 import java.util.UUID;
33
34 import org.apache.directory.mavibot.btree.BTree;
35 import org.apache.directory.mavibot.btree.BTreeConfiguration;
36 import org.apache.directory.mavibot.btree.Cursor;
37 import org.apache.directory.mavibot.btree.Tuple;
38 import org.apache.directory.mavibot.btree.serializer.IntSerializer;
39 import org.apache.directory.mavibot.btree.serializer.StringSerializer;
40 import org.junit.Test;
41
42
43
44
45
46
47
48 public class BTreeDuplicateKeyTest
49 {
50 @Test
51 public void testInsertNullValue() throws IOException
52 {
53 IntSerializer serializer = new IntSerializer();
54
55 BTree<Integer, Integer> btree = new BTree<Integer, Integer>( "master", serializer, serializer );
56 btree.init();
57
58 btree.insert( 1, null );
59
60 Cursor<Integer, Integer> cursor = btree.browse();
61 assertTrue( cursor.hasNext() );
62
63 Tuple<Integer, Integer> t = cursor.next();
64
65 assertEquals( Integer.valueOf( 1 ), t.getKey() );
66 assertEquals( null, t.getValue() );
67
68 cursor.close();
69 }
70
71
72 @Test
73 public void testBrowseEmptyTree() throws IOException
74 {
75 IntSerializer serializer = new IntSerializer();
76
77 BTree<Integer, Integer> btree = new BTree<Integer, Integer>( "master", serializer, serializer );
78 btree.init();
79
80 Cursor<Integer, Integer> cursor = btree.browse();
81 assertFalse( cursor.hasNext() );
82 assertFalse( cursor.hasPrev() );
83
84 try
85 {
86 cursor.next();
87 fail( "Should not reach here" );
88 }
89 catch ( NoSuchElementException e )
90 {
91 assertTrue( true );
92 }
93
94 try
95 {
96 cursor.prev();
97 fail( "Should not reach here" );
98 }
99 catch ( NoSuchElementException e )
100 {
101 assertTrue( true );
102 }
103
104 cursor.close();
105 }
106
107
108 @Test
109 public void testDuplicateKey() throws IOException
110 {
111 IntSerializer serializer = new IntSerializer();
112
113 BTreeConfiguration<Integer, Integer> config = new BTreeConfiguration<Integer, Integer>();
114 config.setAllowDuplicates( true );
115 config.setName( "master" );
116 config.setSerializers( serializer, serializer );
117 BTree<Integer, Integer> btree = new BTree<Integer, Integer>( config );
118
119 btree.insert( 1, 1 );
120 btree.insert( 1, 2 );
121
122 Cursor<Integer, Integer> cursor = btree.browse();
123 assertTrue( cursor.hasNext() );
124
125 Tuple<Integer, Integer> t = cursor.next();
126
127 assertEquals( Integer.valueOf( 1 ), t.getKey() );
128 assertEquals( Integer.valueOf( 1 ), t.getValue() );
129
130 assertTrue( cursor.hasNext() );
131
132 t = cursor.next();
133
134 assertEquals( Integer.valueOf( 1 ), t.getKey() );
135 assertEquals( Integer.valueOf( 2 ), t.getValue() );
136
137 assertFalse( cursor.hasNext() );
138
139
140 assertTrue( cursor.hasPrev() );
141
142 t = cursor.prev();
143
144 assertEquals( Integer.valueOf( 1 ), t.getKey() );
145 assertEquals( Integer.valueOf( 2 ), t.getValue() );
146
147 assertTrue( cursor.hasPrev() );
148
149 t = cursor.prev();
150
151 assertEquals( Integer.valueOf( 1 ), t.getKey() );
152 assertEquals( Integer.valueOf( 1 ), t.getValue() );
153
154 assertFalse( cursor.hasPrev() );
155
156
157 assertTrue( cursor.hasNext() );
158
159 t = cursor.next();
160
161 assertEquals( Integer.valueOf( 1 ), t.getKey() );
162 assertEquals( Integer.valueOf( 1 ), t.getValue() );
163
164 assertTrue( cursor.hasNext() );
165
166 t = cursor.next();
167
168 assertEquals( Integer.valueOf( 1 ), t.getKey() );
169 assertEquals( Integer.valueOf( 2 ), t.getValue() );
170
171 assertFalse( cursor.hasNext() );
172
173 cursor.close();
174 }
175
176
177 @Test
178 public void testGetDuplicateKey() throws Exception
179 {
180 IntSerializer serializer = new IntSerializer();
181
182 BTreeConfiguration<Integer, Integer> config = new BTreeConfiguration<Integer, Integer>();
183 config.setAllowDuplicates( true );
184 config.setName( "master" );
185 config.setSerializers( serializer, serializer );
186 BTree<Integer, Integer> btree = new BTree<Integer, Integer>( config );
187
188 Integer retVal = btree.insert( 1, 1 );
189 assertNull( retVal );
190
191 retVal = btree.insert( 1, 2 );
192 assertNull( retVal );
193
194
195 retVal = btree.insert( 1, 2 );
196 assertEquals( Integer.valueOf( 2 ), retVal );
197
198 assertEquals( Integer.valueOf( 1 ), btree.get( 1 ) );
199 assertTrue( btree.contains( 1, 1 ) );
200 assertTrue( btree.contains( 1, 2 ) );
201
202 assertFalse( btree.contains( 1, 0 ) );
203 assertFalse( btree.contains( 0, 1 ) );
204 assertFalse( btree.contains( 0, 0 ) );
205 assertFalse( btree.contains( null, 0 ) );
206 assertFalse( btree.contains( 0, null ) );
207 assertFalse( btree.contains( null, null ) );
208 }
209
210
211 @Test
212 public void testRemoveDuplicateKey() throws Exception
213 {
214 IntSerializer serializer = new IntSerializer();
215
216 BTreeConfiguration<Integer, Integer> config = new BTreeConfiguration<Integer, Integer>();
217 config.setAllowDuplicates( true );
218 config.setName( "master" );
219 config.setSerializers( serializer, serializer );
220 BTree<Integer, Integer> btree = new BTree<Integer, Integer>( config );
221
222 btree.insert( 1, 1 );
223 btree.insert( 1, 2 );
224
225 assertEquals( 2l, btree.getNbElems() );
226
227 Tuple<Integer, Integer> t = btree.delete( 1, 1 );
228 assertEquals( Integer.valueOf( 1 ), t.getKey() );
229 assertEquals( Integer.valueOf( 1 ), t.getValue() );
230
231 assertEquals( 1l, btree.getNbElems() );
232
233 t = btree.delete( 1, 2 );
234 assertEquals( Integer.valueOf( 1 ), t.getKey() );
235 assertEquals( Integer.valueOf( 2 ), t.getValue() );
236
237 assertEquals( 0l, btree.getNbElems() );
238
239 t = btree.delete( 1, 2 );
240 assertNull( t );
241 }
242
243
244 @Test
245 public void testFullPage() throws Exception
246 {
247 StringSerializer serializer = new StringSerializer();
248
249 BTreeConfiguration<String, String> config = new BTreeConfiguration<String, String>();
250 config.setAllowDuplicates( true );
251 config.setName( "master" );
252 config.setSerializers( serializer, serializer );
253 BTree<String, String> btree = new BTree<String, String>( config );
254
255 int i = 7;
256 for ( char ch = 'a'; ch <= 'z'; ch++ )
257 {
258 for( int k = 0; k< i; k++ )
259 {
260 btree.insert( String.valueOf( ch ), UUID.randomUUID().toString() );
261 }
262 }
263
264 Cursor<String, String> cursor = btree.browse();
265
266 char ch = 'a';
267 int k = 0;
268
269 while ( cursor.hasNext() )
270 {
271 Tuple<String, String> t = cursor.next();
272 assertEquals( String.valueOf( ch ), t.getKey() );
273 k++;
274
275 if( ( k % i ) == 0 )
276 {
277 ch++;
278 }
279 }
280
281 assertEquals( ( 'z' + 1 ) , ch );
282
283 ch = 'z';
284
285 while(cursor.hasPrev())
286 {
287 Tuple<String, String> t = cursor.prev();
288 assertEquals( String.valueOf( ch ), t.getKey() );
289 k--;
290
291 if( ( k % i ) == 0 )
292 {
293 ch--;
294 }
295 }
296
297 assertEquals( ( 'a' - 1 ) , ch );
298 cursor.close();
299 }
300
301 @Test
302 public void testMoveFirst() throws Exception
303 {
304 StringSerializer serializer = new StringSerializer();
305
306 BTreeConfiguration<String, String> config = new BTreeConfiguration<String, String>();
307 config.setAllowDuplicates( true );
308 config.setName( "master" );
309 config.setSerializers( serializer, serializer );
310 BTree<String, String> btree = new BTree<String, String>( config );
311
312 for ( char ch = 'a'; ch <= 'z'; ch++ )
313 {
314 btree.insert( String.valueOf( ch ), UUID.randomUUID().toString() );
315 }
316
317
318 btree.insert( String.valueOf( 'a' ), UUID.randomUUID().toString() );
319
320 Cursor<String, String> cursor = btree.browseFrom( "c" );
321
322 int i = 0;
323 while( cursor.hasNext() )
324 {
325 assertNotNull( cursor.next() );
326 i++;
327 }
328 assertEquals( 24, i );
329
330
331 cursor.beforeFirst();
332 assertTrue( cursor.hasNext() );
333 assertEquals( "c", cursor.next().getKey() );
334
335 i = 0;
336 while( cursor.hasNext() )
337 {
338 assertNotNull( cursor.next() );
339 i++;
340 }
341 assertEquals( 23, i );
342
343 cursor.close();
344
345 cursor = btree.browse();
346
347 i = 0;
348 while( cursor.hasNext() )
349 {
350 assertNotNull( cursor.next() );
351 i++;
352 }
353 assertEquals( 27, i );
354
355
356 cursor.beforeFirst();
357 assertTrue( cursor.hasNext() );
358 assertEquals( "a", cursor.next().getKey() );
359
360 i = 0;
361 while( cursor.hasNext() )
362 {
363 assertNotNull( cursor.next() );
364 i++;
365 }
366 assertEquals( 26, i );
367 }
368
369
370 @Test(expected = NoSuchElementException.class)
371 public void testMoveLast() throws Exception
372 {
373 StringSerializer serializer = new StringSerializer();
374
375 BTreeConfiguration<String, String> config = new BTreeConfiguration<String, String>();
376 config.setAllowDuplicates( true );
377 config.setName( "master" );
378 config.setSerializers( serializer, serializer );
379 BTree<String, String> btree = new BTree<String, String>( config );
380
381 for ( char ch = 'a'; ch <= 'z'; ch++ )
382 {
383 btree.insert( String.valueOf( ch ), UUID.randomUUID().toString() );
384 }
385
386 btree.insert( String.valueOf( 'z' ), UUID.randomUUID().toString() );
387
388 Cursor<String, String> cursor = btree.browseFrom( "c" );
389 cursor.afterLast();
390
391 assertFalse( cursor.hasNext() );
392 assertTrue( cursor.hasPrev() );
393 assertEquals( "z", cursor.prev().getKey() );
394 assertEquals( "z", cursor.prev().getKey() );
395 assertEquals( "y", cursor.prev().getKey() );
396
397 cursor.beforeFirst();
398 assertEquals( "c", cursor.next().getKey() );
399
400 cursor.afterLast();
401 assertFalse( cursor.hasNext() );
402
403 cursor.next();
404 }
405
406
407 @Test(expected = NoSuchElementException.class)
408 public void testMoveToNextPrevNonDuplicateKey() throws Exception
409 {
410 StringSerializer serializer = new StringSerializer();
411
412 BTreeConfiguration<String, String> config = new BTreeConfiguration<String, String>();
413 config.setAllowDuplicates( true );
414 config.setName( "master" );
415 config.setSerializers( serializer, serializer );
416 BTree<String, String> btree = new BTree<String, String>( config );
417
418 int i = 7;
419 for ( char ch = 'a'; ch <= 'z'; ch++ )
420 {
421 for( int k = 0; k< i; k++ )
422 {
423 btree.insert( String.valueOf( ch ), String.valueOf( k ) );
424 }
425 }
426
427 Cursor<String, String> cursor = btree.browse();
428
429 assertTrue( cursor.hasNext() );
430 assertFalse( cursor.hasPrev() );
431 for(int k =0; k < 2; k++)
432 {
433 assertEquals( "a", cursor.next().getKey() );
434 }
435
436 assertEquals( "a", cursor.next().getKey() );
437
438 cursor.moveToNextNonDuplicateKey();
439
440 assertEquals( "b", cursor.next().getKey() );
441
442 for ( char ch = 'b'; ch < 'z'; ch++ )
443 {
444 assertEquals( String.valueOf( ch ), cursor.next().getKey() );
445 cursor.moveToNextNonDuplicateKey();
446 char t = ch;
447 assertEquals( String.valueOf( ++t ), cursor.next().getKey() );
448 }
449
450 for(int k =0; k < i-1; k++)
451 {
452 assertEquals( "z", cursor.next().getKey() );
453 }
454
455 assertFalse( cursor.hasNext() );
456 assertTrue( cursor.hasPrev() );
457 Tuple<String, String> tuple = cursor.prev();
458 assertEquals( "z", tuple.getKey() );
459 assertEquals( "6", tuple.getValue() );
460
461 for ( char ch = 'z'; ch > 'a'; ch-- )
462 {
463 char t = ch;
464 t--;
465
466 assertEquals( String.valueOf( ch ), cursor.prev().getKey() );
467
468 cursor.moveToPrevNonDuplicateKey();
469
470 tuple = cursor.prev();
471 assertEquals( String.valueOf( t ), tuple.getKey() );
472 }
473
474 for(int k =5; k >=0; k--)
475 {
476 tuple = cursor.prev();
477 assertEquals( "a", tuple.getKey() );
478 assertEquals( String.valueOf( k ), tuple.getValue() );
479 }
480
481 assertTrue( cursor.hasNext() );
482 assertFalse( cursor.hasPrev() );
483 tuple = cursor.next();
484 assertEquals( "a", tuple.getKey() );
485 assertEquals( "0", tuple.getValue() );
486
487 cursor.close();
488
489 cursor = btree.browseFrom("y");
490 cursor.moveToNextNonDuplicateKey();
491 assertTrue( cursor.hasPrev() );
492 tuple = cursor.prev();
493 assertEquals( "y", tuple.getKey() );
494 assertEquals( "6", tuple.getValue() );
495 cursor.close();
496
497 cursor = btree.browse();
498 cursor.beforeFirst();
499 assertFalse( cursor.hasPrev() );
500
501 cursor.prev();
502 }
503
504
505
506
507
508
509
510
511 @Test
512 public void testMoveToNextAndPrevWithPageBoundaries() throws Exception
513 {
514 IntSerializer serializer = new IntSerializer();
515
516 BTreeConfiguration<Integer, Integer> config = new BTreeConfiguration<Integer, Integer>();
517 config.setAllowDuplicates( true );
518 config.setName( "master" );
519 config.setPageSize( 4 );
520 config.setSerializers( serializer, serializer );
521 BTree<Integer, Integer> btree = new BTree<Integer, Integer>( config );
522
523 int i = 7;
524 for ( int k=0; k < i; k++ )
525 {
526 btree.insert( k, k );
527 }
528
529
530 Cursor<Integer, Integer> cursor = btree.browseFrom(3);
531 cursor.moveToNextNonDuplicateKey();
532
533 assertTrue( cursor.hasNext() );
534 Tuple<Integer, Integer> tuple = cursor.next();
535 assertEquals( Integer.valueOf( 4 ), tuple.getKey() );
536 assertEquals( Integer.valueOf( 4 ), tuple.getValue() );
537 cursor.close();
538
539 cursor = btree.browseFrom(3);
540 cursor.moveToNextNonDuplicateKey();
541
542 assertTrue( cursor.hasPrev() );
543 tuple = cursor.prev();
544 assertEquals( Integer.valueOf( 3 ), tuple.getKey() );
545 assertEquals( Integer.valueOf( 3 ), tuple.getValue() );
546 cursor.close();
547
548
549 cursor = btree.browseFrom(4);
550 cursor.moveToPrevNonDuplicateKey();
551
552 assertTrue( cursor.hasPrev() );
553 tuple = cursor.prev();
554 assertEquals( Integer.valueOf( 3 ), tuple.getKey() );
555 assertEquals( Integer.valueOf( 3 ), tuple.getValue() );
556
557
558
559
560
561
562
563 cursor.close();
564
565
566 cursor = btree.browseFrom(6);
567 cursor.moveToNextNonDuplicateKey();
568 assertFalse( cursor.hasNext() );
569 assertTrue( cursor.hasPrev() );
570 tuple = cursor.prev();
571 assertEquals( Integer.valueOf( 6 ), tuple.getKey() );
572 assertEquals( Integer.valueOf( 6 ), tuple.getValue() );
573 cursor.close();
574
575 cursor = btree.browse();
576 cursor.moveToPrevNonDuplicateKey();
577 assertTrue( cursor.hasNext() );
578 assertFalse( cursor.hasPrev() );
579 tuple = cursor.next();
580 assertEquals( Integer.valueOf( 0 ), tuple.getKey() );
581 assertEquals( Integer.valueOf( 0 ), tuple.getValue() );
582 cursor.close();
583 }
584
585
586 @Test
587 public void testNextAfterPrev() throws Exception
588 {
589 IntSerializer serializer = new IntSerializer();
590
591 BTreeConfiguration<Integer, Integer> config = new BTreeConfiguration<Integer, Integer>();
592 config.setAllowDuplicates( true );
593 config.setName( "master" );
594 config.setPageSize( 4 );
595 config.setSerializers( serializer, serializer );
596 BTree<Integer, Integer> btree = new BTree<Integer, Integer>( config );
597
598 int i = 7;
599 for ( int k=0; k < i; k++ )
600 {
601 btree.insert( k, k );
602 }
603
604
605 Cursor<Integer, Integer> cursor = btree.browseFrom(4);
606
607 assertTrue( cursor.hasNext() );
608 Tuple<Integer, Integer> tuple = cursor.next();
609 assertEquals( Integer.valueOf( 4 ), tuple.getKey() );
610 assertEquals( Integer.valueOf( 4 ), tuple.getValue() );
611
612 assertTrue( cursor.hasPrev() );
613 tuple = cursor.prev();
614 assertEquals( Integer.valueOf( 4 ), tuple.getKey() );
615 assertEquals( Integer.valueOf( 4 ), tuple.getValue() );
616
617 assertTrue( cursor.hasNext() );
618 tuple = cursor.next();
619 assertEquals( Integer.valueOf( 4 ), tuple.getKey() );
620 assertEquals( Integer.valueOf( 4 ), tuple.getValue() );
621 cursor.close();
622
623 }
624
625
626
627
628
629
630
631 @Test
632 public void testMoveToNextAndTraverseBackward() throws Exception
633 {
634 IntSerializer serializer = new IntSerializer();
635
636 BTreeConfiguration<Integer, Integer> config = new BTreeConfiguration<Integer, Integer>();
637 config.setAllowDuplicates( true );
638 config.setName( "master" );
639 config.setPageSize( 8 );
640 config.setSerializers( serializer, serializer );
641 BTree<Integer, Integer> btree = new BTree<Integer, Integer>( config );
642
643 int i = 5;
644 for ( int k=0; k < i; k++ )
645 {
646 btree.insert( k, k );
647 }
648
649
650 Cursor<Integer, Integer> cursor = btree.browseFrom(4);
651 cursor.moveToNextNonDuplicateKey();
652
653 int currentKey = 4;
654 while( cursor.hasPrev() )
655 {
656 assertEquals( Integer.valueOf( currentKey ), cursor.prev().getKey() );
657 currentKey--;
658 }
659
660 cursor.close();
661 }
662
663
664
665
666
667
668
669 @Test
670 public void testMoveToPrevAndTraverseForward() throws Exception
671 {
672 IntSerializer serializer = new IntSerializer();
673
674 BTreeConfiguration<Integer, Integer> config = new BTreeConfiguration<Integer, Integer>();
675 config.setAllowDuplicates( true );
676 config.setName( "master" );
677 config.setPageSize( 8 );
678 config.setSerializers( serializer, serializer );
679 BTree<Integer, Integer> btree = new BTree<Integer, Integer>( config );
680
681 int i = 5;
682 for ( int k=0; k < i; k++ )
683 {
684 btree.insert( k, k );
685 }
686
687
688 Cursor<Integer, Integer> cursor = btree.browseFrom(0);
689 cursor.moveToPrevNonDuplicateKey();
690
691 int currentKey = 0;
692 while( cursor.hasNext() )
693 {
694 assertEquals( Integer.valueOf( currentKey ), cursor.next().getKey() );
695 currentKey++;
696 }
697
698 cursor.close();
699 }
700
701 }