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.lang.reflect.Array;
32 import java.util.ArrayList;
33 import java.util.HashSet;
34 import java.util.List;
35 import java.util.Random;
36 import java.util.Set;
37
38 import org.apache.directory.mavibot.btree.BTree;
39 import org.apache.directory.mavibot.btree.BTreeConfiguration;
40 import org.apache.directory.mavibot.btree.Cursor;
41 import org.apache.directory.mavibot.btree.Leaf;
42 import org.apache.directory.mavibot.btree.MemoryHolder;
43 import org.apache.directory.mavibot.btree.Node;
44 import org.apache.directory.mavibot.btree.Page;
45 import org.apache.directory.mavibot.btree.Tuple;
46 import org.apache.directory.mavibot.btree.exception.EndOfFileExceededException;
47 import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
48 import org.apache.directory.mavibot.btree.serializer.IntSerializer;
49 import org.apache.directory.mavibot.btree.serializer.LongSerializer;
50 import org.apache.directory.mavibot.btree.serializer.StringSerializer;
51 import org.junit.Ignore;
52 import org.junit.Test;
53
54
55
56
57
58
59
60 public class InMemoryBTreeTest
61 {
62
63 private static int[] sortedValues = new int[]
64 {
65 0, 1, 2, 4, 5, 6, 8, 9, 11, 12,
66 13, 14, 16, 19, 21, 22, 23, 25, 26, 28,
67 30, 31, 32, 34, 36, 37, 38, 39, 41, 42,
68 44, 45, 47, 50, 52, 53, 54, 55, 56, 58,
69 59, 60, 63, 64, 67, 68, 70, 72, 73, 74,
70 76, 77, 79, 80, 81, 82, 85, 88, 89, 90,
71 92, 93, 95, 97, 98, 100, 101, 102, 103, 104,
72 105, 106, 107, 109, 110, 111, 112, 117, 118, 120,
73 121, 128, 129, 130, 131, 132, 135, 136, 137, 138,
74 139, 140, 141, 142, 143, 146, 147, 148, 149, 150,
75 152, 154, 156, 160, 161, 162, 163, 165, 167, 168,
76 169, 171, 173, 174, 175, 176, 177, 178, 179, 180,
77 181, 182, 183, 189, 190, 193, 194, 195, 199, 200,
78 202, 203, 205, 206, 207, 208, 209, 210, 212, 215,
79 216, 217, 219, 220, 222, 223, 224, 225, 226, 227,
80 228, 230, 231, 235, 236, 238, 239, 241, 242, 243,
81 245, 246, 247, 249, 250, 251, 252, 254, 256, 257,
82 258, 259, 261, 262, 263, 264, 266, 268, 272, 273,
83 274, 276, 277, 278, 279, 282, 283, 286, 289, 290,
84 292, 293, 294, 296, 298, 299, 300, 301, 303, 305,
85 308, 310, 316, 317, 318, 319, 322, 323, 324, 326,
86 327, 329, 331, 333, 334, 335, 336, 337, 338, 339,
87 340, 341, 346, 347, 348, 349, 350, 351, 352, 353,
88 355, 356, 357, 358, 359, 361, 365, 366, 373, 374,
89 375, 379, 380, 381, 382, 384, 385, 387, 388, 389,
90 390, 392, 393, 395, 396, 397, 398, 399, 400, 401,
91 404, 405, 406, 407, 410, 411, 412, 416, 417, 418,
92 420, 421, 422, 424, 426, 427, 428, 430, 431, 432,
93 433, 436, 439, 441, 443, 444, 445, 446, 447, 448,
94 449, 450, 451, 452, 453, 454, 455, 456, 458, 459,
95 464, 466, 469, 470, 471, 472, 475, 477, 478, 482,
96 483, 484, 485, 486, 488, 490, 491, 492, 493, 495,
97 496, 497, 500, 502, 503, 504, 505, 506, 507, 509,
98 510, 514, 516, 518, 520, 521, 523, 524, 526, 527,
99 528, 529, 530, 532, 533, 535, 538, 539, 540, 542,
100 543, 544, 546, 547, 549, 550, 551, 553, 554, 558,
101 559, 561, 563, 564, 566, 567, 568, 569, 570, 571,
102 572, 576, 577, 578, 580, 582, 583, 586, 588, 589,
103 590, 592, 593, 596, 597, 598, 599, 600, 601, 604,
104 605, 606, 607, 609, 610, 613, 615, 617, 618, 619,
105 620, 621, 626, 627, 628, 631, 632, 633, 635, 636,
106 637, 638, 639, 640, 641, 643, 645, 647, 648, 649,
107 650, 651, 652, 653, 655, 656, 658, 659, 660, 662,
108 666, 669, 673, 674, 675, 676, 677, 678, 680, 681,
109 682, 683, 685, 686, 687, 688, 689, 690, 691, 692,
110 693, 694, 696, 698, 699, 700, 701, 705, 708, 709,
111 711, 713, 714, 715, 719, 720, 723, 725, 726, 727,
112 728, 731, 732, 733, 734, 735, 736, 739, 740, 743,
113 744, 745, 746, 747, 749, 750, 752, 753, 762, 763,
114 765, 766, 768, 770, 772, 773, 774, 776, 777, 779,
115 782, 784, 785, 788, 790, 791, 793, 794, 795, 798,
116 799, 800, 801, 803, 804, 805, 808, 810, 812, 813,
117 814, 816, 818, 821, 822, 823, 824, 827, 828, 829,
118 831, 832, 833, 834, 835, 837, 838, 839, 840, 843,
119 846, 847, 849, 852, 853, 854, 856, 857, 859, 860,
120 863, 864, 865, 866, 867, 868, 869, 872, 873, 877,
121 880, 881, 882, 883, 887, 888, 889, 890, 891, 894,
122 895, 897, 898, 899, 902, 904, 905, 907, 908, 910,
123 911, 912, 915, 916, 917, 918, 919, 923, 925, 926,
124 927, 928, 929, 930, 932, 935, 936, 937, 938, 939,
125 944, 945, 947, 952, 953, 954, 955, 956, 957, 958,
126 960, 967, 970, 971, 972, 974, 975, 976, 978, 979,
127 980, 981, 983, 984, 985, 987, 988, 989, 991, 995
128 };
129
130
131
132
133
134 private boolean checkTreeLong( Set<Long> expected, BTree<Long, String> btree ) throws IOException
135 {
136
137
138 for ( Long key : expected )
139 {
140 try
141 {
142 btree.get( key );
143 }
144 catch ( KeyNotFoundException knfe )
145 {
146 return false;
147 }
148 }
149
150 return true;
151 }
152
153
154
155
156
157
158
159
160
161 @Test
162 public void testPageInsert() throws Exception
163 {
164 Set<Long> expected = new HashSet<Long>();
165 List<Long> added = new ArrayList<Long>();
166
167 Random random = new Random( System.nanoTime() );
168
169 int nbError = 0;
170
171 long l1 = System.currentTimeMillis();
172 int n = 0;
173 long delta = l1;
174 int nbTrees = 1000;
175 int nbElems = 1000;
176
177 for ( int j = 0; j < nbTrees; j++ )
178 {
179 BTree<Long, String> btree = new BTree<Long, String>( "test", new LongSerializer(), new StringSerializer() );
180 btree.setPageSize( 32 );
181
182 for ( int i = 0; i < nbElems; i++ )
183 {
184 Long key = ( long ) random.nextInt( 1024 );
185 String value = "V" + key;
186 expected.add( key );
187 added.add( key );
188
189
190
191 try
192 {
193 btree.insert( key, value );
194 }
195 catch ( Exception e )
196 {
197 e.printStackTrace();
198 System.out.println( btree );
199 System.out.println( "Error while adding " + value );
200 nbError++;
201 return;
202 }
203 }
204
205 assertTrue( checkTreeLong( expected, btree ) );
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228 if ( j % 10000 == 0 )
229 {
230 if ( n > 0 )
231 {
232 long t0 = System.currentTimeMillis();
233 System.out.println( "Delta" + n + ": " + ( t0 - delta ) );
234 delta = t0;
235 }
236
237 n++;
238 }
239
240 expected.clear();
241 added.clear();
242
243 btree.close();
244 }
245
246 long l2 = System.currentTimeMillis();
247
248 System.out.println( "Delta : " + ( l2 - l1 ) + ", nbError = " + nbError
249 + ", Nb insertion per second : " + ( nbTrees * nbElems * 1000 ) / ( l2 - l1 ) );
250 }
251
252
253
254
255
256
257
258
259
260
261 @Test
262 public void testPageDeleteRandom() throws IOException
263 {
264 Set<Long> expected = new HashSet<Long>();
265 List<Long> added = new ArrayList<Long>();
266
267 Random random = new Random( System.nanoTime() );
268
269 int nbError = 0;
270
271 long l1 = System.currentTimeMillis();
272 int n = 0;
273 long delta = l1;
274 int nbTrees = 1000;
275 int nbElems = 1000;
276
277 for ( int j = 0; j < nbTrees; j++ )
278 {
279 BTree<Long, String> btree = new BTree<Long, String>( "test", new LongSerializer(), new StringSerializer() );
280 btree.setPageSize( 8 );
281
282 for ( int i = 0; i < nbElems; i++ )
283 {
284 Long key = ( long ) random.nextInt( 1024 );
285 String value = "V" + key;
286 expected.add( key );
287 added.add( key );
288
289
290
291 try
292 {
293 btree.insert( key, value );
294 }
295 catch ( Exception e )
296 {
297 e.printStackTrace();
298 System.out.println( btree );
299 System.out.println( "Error while adding " + value );
300 nbError++;
301 return;
302 }
303 }
304
305 assertTrue( checkTreeLong( expected, btree ) );
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330 for ( long element : expected )
331 {
332
333
334
335 Tuple<Long, String> tuple = btree.delete( element );
336
337 if ( tuple == null )
338 {
339 System.out.println( btree );
340 }
341
342 assertEquals( Long.valueOf( element ), tuple.getKey() );
343
344 checkNull( btree, element );
345
346
347 }
348
349 if ( j % 10000 == 0 )
350 {
351 if ( n > 0 )
352 {
353 long t0 = System.currentTimeMillis();
354 System.out.println( "Delta" + n + ": " + ( t0 - delta ) );
355 delta = t0;
356 }
357
358 n++;
359
360 }
361
362 expected.clear();
363 added.clear();
364
365 btree.close();
366 }
367
368 long l2 = System.currentTimeMillis();
369
370 System.out.println( "Delta : " + ( l2 - l1 ) + ", nbError = " + nbError
371 + ", Nb deletion per second : " + ( nbTrees * nbElems * 1000 ) / ( l2 - l1 ) );
372 }
373
374
375 @Test
376 public void testDeleteDebug() throws IOException
377 {
378 long[] values = new long[]
379 {
380 148, 746, 525, 327, 1, 705, 171, 1023, 769, 1021,
381 128, 772, 744, 771, 925, 884, 346, 519, 989, 350,
382 649, 895, 464, 164, 190, 298, 203, 69, 483, 38,
383 266, 83, 88, 285, 879, 342, 231, 432, 722, 432,
384 258, 307, 237, 151, 43, 36, 135, 166, 325, 886,
385 878, 307, 925, 835, 800, 895, 519, 947, 703, 27,
386 324, 668, 40, 943, 804, 230, 223, 584, 828, 575,
387 69, 955, 344, 325, 896, 423, 855, 783, 225, 447,
388 28, 23, 262, 679, 782, 517, 412, 878, 641, 940,
389 368, 245, 1005, 226, 939, 320, 396, 437, 373, 61
390 };
391
392 BTree<Long, String> btree = new BTree<Long, String>( "test", new LongSerializer(), new StringSerializer() );
393 btree.setPageSize( 8 );
394
395 for ( long value : values )
396 {
397 String strValue = "V" + value;
398
399 try
400 {
401 btree.insert( value, strValue );
402 }
403 catch ( Exception e )
404 {
405 e.printStackTrace();
406 System.out.println( btree );
407 System.out.println( "Error while adding " + value );
408 return;
409 }
410 }
411
412 int i = 0;
413
414 long[] deletes = new long[]
415 {
416 1,
417 828,
418 285,
419 804,
420 258,
421 262,
422 };
423
424 for ( long value : deletes )
425 {
426
427 i++;
428 Tuple<Long, String> tuple = btree.delete( value );
429
430 if ( tuple != null )
431 {
432 assertEquals( Long.valueOf( value ), tuple.getKey() );
433 }
434
435 checkNull( btree, value );
436 }
437
438 btree.close();
439 }
440
441
442
443
444
445 @Test
446 public void testPageDelete() throws Exception
447 {
448 Set<Long> expected = new HashSet<Long>();
449 List<Long> added = new ArrayList<Long>();
450
451 Random random = new Random( System.nanoTime() );
452
453 BTree<Long, String> btree = new BTree<Long, String>( "test", new LongSerializer(), new StringSerializer() );
454 btree.setPageSize( 8 );
455
456
457 for ( int i = 0; i < 8; i++ )
458 {
459 Long key = ( long ) random.nextInt( 1024 );
460 String value = "V" + key;
461 added.add( key );
462
463 try
464 {
465 btree.insert( key, value );
466 }
467 catch ( Exception e )
468 {
469 e.printStackTrace();
470 System.out.println( btree );
471 System.out.println( "Error while adding " + value );
472 return;
473 }
474 }
475
476 assertTrue( checkTreeLong( expected, btree ) );
477
478
479 for ( long key : added )
480 {
481
482 try
483 {
484 btree.delete( key );
485 }
486 catch ( Exception e )
487 {
488 e.printStackTrace();
489 System.out.println( btree );
490 System.out.println( "Error while deleting " + key );
491 return;
492 }
493
494 assertTrue( checkTreeLong( expected, btree ) );
495 }
496
497 btree.close();
498 }
499
500
501
502
503
504
505 @Test
506 @Ignore
507 public void testPageInsertDebug() throws Exception
508 {
509 BTree<Long, String> btree = new BTree<Long, String>( "test", new LongSerializer(), new StringSerializer() );
510 btree.setPageSize( 4 );
511
512 Long[] elems = new Long[]
513 {
514 235L, 135L, 247L, 181L, 12L, 112L, 117L, 253L,
515 37L, 158L, 56L, 118L, 184L, 101L, 173L, 126L,
516 61L, 81L, 140L, 173L, 32L, 163L, 224L, 114L,
517 133L, 18L, 14L, 82L, 107L, 219L, 244L, 255L,
518 6L, 103L, 170L, 151L, 134L, 196L, 155L, 97L,
519 80L, 122L, 89L, 253L, 33L, 101L, 56L, 168L,
520 253L, 187L, 99L, 58L, 151L, 206L, 34L, 96L,
521 20L, 188L, 143L, 150L, 76L, 111L, 234L, 66L,
522 12L, 194L, 164L, 190L, 19L, 192L, 161L, 147L,
523 92L, 89L, 237L, 187L, 250L, 13L, 233L, 34L,
524 187L, 232L, 248L, 237L, 129L, 1L, 233L, 252L,
525 18L, 98L, 56L, 121L, 162L, 233L, 29L, 48L,
526 176L, 48L, 182L, 130L
527 };
528
529 int size = 0;
530 for ( Long elem : elems )
531 {
532 size++;
533 String value = "V" + elem;
534 btree.insert( elem, value );
535
536 System.out.println( "Adding " + elem + " :\n" + btree );
537
538 for ( int i = 0; i < size; i++ )
539 {
540 try
541 {
542 btree.get( elems[i] );
543 }
544 catch ( KeyNotFoundException knfe )
545 {
546 System.out.println( "Bad tree, missing " + elems[i] + ", " + btree );
547 }
548 }
549
550 if ( size == 27 )
551 {
552 System.out.println( btree );
553 }
554
555 }
556
557
558
559 btree.close();
560 }
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611 @Test
612 public void testBrowseForward() throws Exception
613 {
614
615 BTree<Integer, String> btree = new BTree<Integer, String>( "test", new IntSerializer(), new StringSerializer() );
616 btree.setPageSize( 8 );
617
618
619 for ( int value : sortedValues )
620 {
621 String strValue = "V" + value;
622
623 btree.insert( value, strValue );
624 }
625
626
627 for ( int key : sortedValues )
628 {
629 String value = btree.get( key );
630
631 assertNotNull( value );
632 }
633
634
635 int pos = 10;
636 Cursor<Integer, String> cursor = btree.browseFrom( sortedValues[pos] );
637
638 while ( cursor.hasNext() )
639 {
640 Tuple<Integer, String> tuple = cursor.next();
641
642 assertNotNull( tuple );
643 Integer val = sortedValues[pos];
644 Integer res = tuple.getKey();
645 assertEquals( val, res );
646 pos++;
647 }
648
649 cursor.close();
650
651
652 cursor = btree.browseFrom( 7 );
653
654
655 pos = 6;
656
657 while ( cursor.hasNext() )
658 {
659 Tuple<Integer, String> tuple = cursor.next();
660
661 assertNotNull( tuple );
662 Integer val = sortedValues[pos];
663 Integer res = tuple.getKey();
664 assertEquals( val, res );
665 pos++;
666 }
667
668 cursor.close();
669
670
671 cursor = btree.browse();
672
673 pos = 0;
674
675 while ( cursor.hasNext() )
676 {
677 Tuple<Integer, String> tuple = cursor.next();
678
679 assertNotNull( tuple );
680 Integer val = sortedValues[pos];
681 Integer res = tuple.getKey();
682 assertEquals( val, res );
683 pos++;
684 }
685
686 cursor.close();
687 btree.close();
688 }
689
690
691
692
693
694
695 @Test
696 public void testBrowseBackward() throws Exception
697 {
698
699 BTree<Integer, String> btree = new BTree<Integer, String>( "test", new IntSerializer(), new StringSerializer() );
700 btree.setPageSize( 8 );
701
702
703 for ( int value : sortedValues )
704 {
705 String strValue = "V" + value;
706
707 btree.insert( value, strValue );
708 }
709
710
711 for ( int key : sortedValues )
712 {
713 String value = btree.get( key );
714
715 assertNotNull( value );
716 }
717
718
719 int pos = 10;
720 Cursor<Integer, String> cursor = btree.browseFrom( sortedValues[pos] );
721
722 while ( cursor.hasPrev() )
723 {
724 Tuple<Integer, String> tuple = cursor.prev();
725
726 pos--;
727
728 assertNotNull( tuple );
729 Integer val = sortedValues[pos];
730 Integer res = tuple.getKey();
731 assertEquals( val, res );
732 }
733
734 cursor.close();
735
736
737 cursor = btree.browseFrom( 7 );
738
739
740 pos = 6;
741
742 while ( cursor.hasPrev() )
743 {
744 Tuple<Integer, String> tuple = cursor.prev();
745
746 pos--;
747 assertNotNull( tuple );
748 Integer val = sortedValues[pos];
749 Integer res = tuple.getKey();
750 assertEquals( val, res );
751 }
752
753 cursor.close();
754
755
756 cursor = btree.browse();
757
758 pos = 0;
759
760 assertFalse( cursor.hasPrev() );
761
762 cursor.close();
763 btree.close();
764 }
765
766
767
768
769
770 @Test
771 public void testBrowseEmptyTree() throws Exception
772 {
773
774 BTree<Integer, String> btree = new BTree<Integer, String>( "test", new IntSerializer(), new StringSerializer() );
775 btree.setPageSize( 8 );
776
777 Cursor<Integer, String> cursor = btree.browse();
778
779 assertFalse( cursor.hasNext() );
780 assertFalse( cursor.hasPrev() );
781
782 cursor.close();
783 btree.close();
784 }
785
786
787
788
789
790 @Test
791 public void testBrowseForwardBackward() throws Exception
792 {
793
794 BTree<Integer, String> btree = new BTree<Integer, String>( "test", new IntSerializer(), new StringSerializer() );
795 btree.setPageSize( 4 );
796
797 for ( int i = 0; i < 16; i++ )
798 {
799 String strValue = "V" + i;
800 btree.insert( i, strValue );
801 }
802
803
804 Cursor<Integer, String> cursor = btree.browseFrom( 8 );
805
806 assertTrue( cursor.hasNext() );
807
808
809 assertEquals( 8, cursor.next().getKey().intValue() );
810
811
812 assertEquals( 9, cursor.next().getKey().intValue() );
813
814
815 assertEquals( 10, cursor.next().getKey().intValue() );
816
817
818 assertEquals( 11, cursor.next().getKey().intValue() );
819
820
821 assertEquals( 12, cursor.next().getKey().intValue() );
822
823 assertTrue( cursor.hasPrev() );
824
825
826 assertEquals( 12, cursor.prev().getKey().intValue() );
827
828
829 assertEquals( 11, cursor.prev().getKey().intValue() );
830
831
832 assertEquals( 10, cursor.prev().getKey().intValue() );
833
834
835 assertEquals( 9, cursor.prev().getKey().intValue() );
836
837
838 assertEquals( 8, cursor.prev().getKey().intValue() );
839
840
841 assertEquals( 7, cursor.prev().getKey().intValue() );
842
843 cursor.close();
844 btree.close();
845 }
846
847
848
849
850
851 @Test
852 public void testDeleteFromFullLeaves() throws Exception
853 {
854
855 BTree<Integer, String> btree = createTwoLevelBTreeFullLeaves();
856
857
858
859
860 btree.delete( 1 );
861
862 checkNull( btree, 1 );
863
864 btree.insert( 1, "V1" );
865
866 btree.delete( 3 );
867
868 checkNull( btree, 3 );
869
870 btree.insert( 3, "V3" );
871
872 btree.delete( 4 );
873
874 checkNull( btree, 4 );
875
876 btree.insert( 4, "V4" );
877
878 btree.delete( 11 );
879
880 checkNull( btree, 11 );
881
882 btree.insert( 11, "V11" );
883
884 btree.delete( 20 );
885
886 checkNull( btree, 20 );
887
888 btree.insert( 20, "V20" );
889
890 btree.delete( 0 );
891
892 checkNull( btree, 0 );
893
894 btree.delete( 5 );
895
896 checkNull( btree, 5 );
897
898 btree.delete( 9 );
899
900 checkNull( btree, 9 );
901
902 btree.close();
903 }
904
905
906
907
908
909 @Test
910 public void testExist() throws IOException
911 {
912
913 BTree<Integer, String> btree = createTwoLevelBTreeFullLeaves();
914
915 for ( int i = 1; i < 21; i++ )
916 {
917 assertTrue( btree.hasKey( 5 ) );
918 }
919
920 assertFalse( btree.hasKey( 0 ) );
921 assertFalse( btree.hasKey( 21 ) );
922 }
923
924
925
926
927
928 @Test
929 public void testDeleteBorrowFromSibling() throws Exception
930 {
931
932 BTree<Integer, String> btree = createTwoLevelBTreeFullLeaves();
933
934
935
936 btree.delete( 3 );
937 btree.delete( 4 );
938
939
940 btree.delete( 19 );
941 btree.delete( 20 );
942
943
944 btree.delete( 11 );
945 btree.delete( 12 );
946
947
948 btree.delete( 1 );
949
950 checkNull( btree, 1 );
951
952
953 btree.delete( 18 );
954
955 checkNull( btree, 18 );
956
957
958 btree.delete( 5 );
959
960 checkNull( btree, 5 );
961
962
963 btree.delete( 16 );
964
965 checkNull( btree, 16 );
966
967 btree.close();
968
969
970 btree = createMultiLevelBTreeLeavesHalfFull();
971
972
973 btree.insert( 8, "V8" );
974 btree.insert( 9, "V9" );
975
976
977 btree.delete( 2 );
978
979 checkNull( btree, 2 );
980
981 btree.delete( 6 );
982
983 checkNull( btree, 6 );
984
985
986 btree.insert( 96, "V96" );
987 btree.insert( 97, "V97" );
988
989
990 btree.delete( 98 );
991
992 checkNull( btree, 98 );
993
994 btree.delete( 99 );
995
996 checkNull( btree, 99 );
997
998
999 btree.insert( 48, "V48" );
1000
1001 btree.delete( 42 );
1002
1003 checkNull( btree, 42 );
1004
1005 btree.insert( 72, "V72" );
1006
1007 btree.delete( 67 );
1008
1009 checkNull( btree, 67 );
1010
1011 btree.close();
1012 }
1013
1014
1015
1016
1017
1018
1019 @Test
1020 public void testBrowseNonExistingKey() throws Exception
1021 {
1022
1023 BTree<Integer, String> btree = new BTree<Integer, String>( "test", new IntSerializer(), new StringSerializer() );
1024 btree.setPageSize( 8 );
1025 for ( int i = 0; i < 11; i++ )
1026 {
1027 btree.insert( i, String.valueOf( i ) );
1028 }
1029
1030 for ( int i = 0; i < 11; i++ )
1031 {
1032 assertNotNull( btree.get( i ) );
1033 }
1034
1035 assertTrue( btree.hasKey( 8 ) );
1036 assertFalse( btree.hasKey( 11 ) );
1037
1038 Cursor<Integer, String> cursor = btree.browseFrom( 11 );
1039 assertFalse( cursor.hasNext() );
1040 }
1041
1042
1043 private Page<Integer, String> createLeaf( BTree<Integer, String> btree, long revision,
1044 Tuple<Integer, String>... tuples )
1045 {
1046 Leaf<Integer, String> leaf = new Leaf<Integer, String>( btree );
1047 int pos = 0;
1048 leaf.revision = revision;
1049 leaf.nbElems = tuples.length;
1050 leaf.keys = new Integer[leaf.nbElems];
1051 leaf.values = ( MemoryHolder<Integer, String>[] ) Array
1052 .newInstance( MemoryHolder.class, leaf.nbElems );
1053
1054 for ( Tuple<Integer, String> tuple : tuples )
1055 {
1056 leaf.keys[pos] = tuple.getKey();
1057 leaf.values[pos] = btree.createHolder( tuple.getValue() );
1058 pos++;
1059 }
1060
1061 return leaf;
1062 }
1063
1064
1065 private void addPage( BTree<Integer, String> btree, Node<Integer, String> node, Page<Integer, String> page, int pos )
1066 throws EndOfFileExceededException, IOException
1067 {
1068 Tuple<Integer, String> leftmost = page.findLeftMost();
1069
1070 if ( pos > 0 )
1071 {
1072 node.keys[pos - 1] = leftmost.getKey();
1073 }
1074
1075 node.children[pos] = btree.createHolder( page );
1076 }
1077
1078
1079
1080
1081
1082 private BTree<Integer, String> createTwoLevelBTreeFullLeaves() throws IOException
1083 {
1084 BTree<Integer, String> btree = new BTree<Integer, String>( "test", new IntSerializer(), new StringSerializer() );
1085 btree.setPageSize( 4 );
1086
1087
1088 int[] keys = new int[]
1089 { 1, 2, 5, 6, 3, 4, 9, 10, 7, 8, 13, 14, 11, 12, 17, 18, 15, 16, 19, 20 };
1090
1091 for ( int key : keys )
1092 {
1093 String value = "V" + key;
1094 btree.insert( key, value );
1095 }
1096
1097 return btree;
1098 }
1099
1100
1101
1102
1103
1104 private BTree<Integer, String> createTwoLevelBTreeHalfFullLeaves() throws IOException
1105 {
1106 BTree<Integer, String> btree = new BTree<Integer, String>( "test", new IntSerializer(), new StringSerializer() );
1107 btree.setPageSize( 4 );
1108
1109
1110 int[] keys = new int[]
1111 { 1, 2, 17, 18, 13, 14, 9, 10, 5, 6, 3 };
1112
1113 for ( int key : keys )
1114 {
1115 String value = "V" + key;
1116 btree.insert( key, value );
1117 }
1118
1119
1120 btree.delete( 3 );
1121
1122 return btree;
1123 }
1124
1125
1126 private Set<Integer> EXPECTED1 = new HashSet<Integer>();
1127
1128
1129
1130
1131
1132 private BTree<Integer, String> createMultiLevelBTreeLeavesHalfFull() throws IOException
1133 {
1134
1135 int pageSize = 4;
1136
1137 BTree<Integer, String> btree = new BTree<Integer, String>( "test", new IntSerializer(), new StringSerializer(),
1138 pageSize );
1139
1140 Node<Integer, String> root = new Node<Integer, String>( btree, 1L, pageSize );
1141
1142
1143 int counter = 1;
1144 for ( int i = 0; i < pageSize + 1; i++ )
1145 {
1146 Node<Integer, String> node = new Node<Integer, String>( btree, 1L, pageSize );
1147
1148 for ( int j = 0; j < pageSize + 1; j++ )
1149 {
1150 int even = counter * 2;
1151
1152 @SuppressWarnings("unchecked")
1153 Page<Integer, String> leaf = createLeaf(
1154 btree,
1155 1L,
1156 new Tuple<Integer, String>( even, "v" + even ),
1157 new Tuple<Integer, String>( even + 1, "v" + ( even + 1 ) )
1158 );
1159
1160 counter += 2;
1161
1162 addPage( btree, node, leaf, j );
1163
1164 EXPECTED1.add( even );
1165 EXPECTED1.add( even + 1 );
1166 }
1167
1168 addPage( btree, root, node, i );
1169 }
1170
1171 btree.setRoot( root );
1172
1173 return btree;
1174 }
1175
1176
1177
1178
1179
1180
1181
1182
1183 private void checkRemoval( BTree<Integer, String> btree, int element, Set<Integer> expected ) throws IOException
1184 {
1185 Tuple<Integer, String> removed = btree.delete( element );
1186 assertEquals( element, removed.getKey().intValue() );
1187 assertEquals( "v" + element, removed.getValue() );
1188
1189 checkNull( btree, element );
1190
1191 expected.remove( element );
1192 checkTree( btree, expected );
1193 }
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203 private void checkTree( BTree<Integer, String> btree, Set<Integer> expected )
1204 {
1205 try
1206 {
1207 Cursor<Integer, String> cursor = btree.browse();
1208 Integer value = null;
1209
1210 while ( cursor.hasNext() )
1211 {
1212 Tuple<Integer, String> tuple = cursor.next();
1213
1214 if ( value == null )
1215 {
1216 value = tuple.getKey();
1217 }
1218 else
1219 {
1220 assertTrue( value < tuple.getKey() );
1221 value = tuple.getKey();
1222 }
1223
1224 assertTrue( expected.contains( value ) );
1225 expected.remove( value );
1226 }
1227
1228 assertEquals( 0, expected.size() );
1229 }
1230 catch ( IOException ioe )
1231 {
1232 fail();
1233 }
1234 }
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244 private void delete( BTree<Integer, String> btree, Set<Integer> expected, int... values ) throws IOException
1245 {
1246 for ( int value : values )
1247 {
1248 btree.delete( value );
1249 expected.remove( value );
1250 }
1251 }
1252
1253
1254
1255
1256
1257
1258 @Test
1259 public void testDeleteMultiLevelsLeadingToLeafMerge() throws Exception
1260 {
1261 BTree<Integer, String> btree = createMultiLevelBTreeLeavesHalfFull();
1262
1263
1264 Tuple<Integer, String> removed = btree.delete( 2 );
1265 assertEquals( 2, removed.getKey().intValue() );
1266 assertEquals( "v2", removed.getValue() );
1267 checkNull( btree, 2 );
1268
1269
1270 removed = btree.delete( 7 );
1271 assertEquals( 7, removed.getKey().intValue() );
1272 assertEquals( "v7", removed.getValue() );
1273 checkNull( btree, 7 );
1274
1275
1276 removed = btree.delete( 6 );
1277 assertEquals( 6, removed.getKey().intValue() );
1278 assertEquals( "v6", removed.getValue() );
1279 checkNull( btree, 6 );
1280
1281
1282 removed = btree.delete( 11 );
1283 assertEquals( 11, removed.getKey().intValue() );
1284 assertEquals( "v11", removed.getValue() );
1285 checkNull( btree, 11 );
1286
1287
1288 removed = btree.delete( 99 );
1289 assertEquals( 99, removed.getKey().intValue() );
1290 assertEquals( "v99", removed.getValue() );
1291 checkNull( btree, 99 );
1292
1293
1294 removed = btree.delete( 98 );
1295 assertEquals( 98, removed.getKey().intValue() );
1296 assertEquals( "v98", removed.getValue() );
1297 checkNull( btree, 98 );
1298
1299
1300 removed = btree.delete( 94 );
1301 assertEquals( 94, removed.getKey().intValue() );
1302 assertEquals( "v94", removed.getValue() );
1303 checkNull( btree, 94 );
1304
1305
1306 removed = btree.delete( 95 );
1307 assertEquals( 95, removed.getKey().intValue() );
1308 assertEquals( "v95", removed.getValue() );
1309 checkNull( btree, 95 );
1310
1311
1312 removed = btree.delete( 22 );
1313 assertEquals( 22, removed.getKey().intValue() );
1314 assertEquals( "v22", removed.getValue() );
1315 checkNull( btree, 22 );
1316
1317
1318 removed = btree.delete( 27 );
1319 assertEquals( 27, removed.getKey().intValue() );
1320 assertEquals( "v27", removed.getValue() );
1321 checkNull( btree, 27 );
1322
1323
1324 removed = btree.delete( 70 );
1325 assertEquals( 70, removed.getKey().intValue() );
1326 assertEquals( "v70", removed.getValue() );
1327 checkNull( btree, 70 );
1328
1329
1330 removed = btree.delete( 71 );
1331 assertEquals( 71, removed.getKey().intValue() );
1332 assertEquals( "v71", removed.getValue() );
1333 checkNull( btree, 71 );
1334
1335
1336 removed = btree.delete( 51 );
1337 assertEquals( 51, removed.getKey().intValue() );
1338 assertEquals( "v51", removed.getValue() );
1339 checkNull( btree, 51 );
1340
1341
1342 removed = btree.delete( 50 );
1343 assertEquals( 50, removed.getKey().intValue() );
1344 assertEquals( "v50", removed.getValue() );
1345 checkNull( btree, 50 );
1346
1347 btree.close();
1348 }
1349
1350
1351
1352
1353
1354
1355 @Test
1356 public void testDelete2LevelsTreeWithHalfFullLeaves() throws Exception
1357 {
1358
1359 BTree<Integer, String> btree = createTwoLevelBTreeHalfFullLeaves();
1360
1361
1362
1363 btree.delete( 10 );
1364 checkNull( btree, 10 );
1365
1366
1367 btree.delete( 9 );
1368 checkNull( btree, 9 );
1369
1370
1371 btree.delete( 13 );
1372 checkNull( btree, 13 );
1373
1374
1375 btree.delete( 14 );
1376 checkNull( btree, 14 );
1377
1378
1379 btree.delete( 18 );
1380 checkNull( btree, 18 );
1381
1382
1383 btree.delete( 5 );
1384 checkNull( btree, 5 );
1385
1386
1387 btree.delete( 6 );
1388 checkNull( btree, 6 );
1389
1390 btree.close();
1391 }
1392
1393
1394
1395
1396
1397
1398
1399
1400 @Test
1401 public void testDeleteMultiLevelsLeadingToNodeBorrowRight1() throws Exception
1402 {
1403 BTree<Integer, String> btree = createMultiLevelBTreeLeavesHalfFull();
1404
1405
1406 delete( btree, EXPECTED1, 2, 3, 6, 7 );
1407
1408
1409 checkRemoval( btree, 10, EXPECTED1 );
1410
1411 btree.close();
1412 }
1413
1414
1415
1416
1417
1418
1419
1420
1421 @Test
1422 public void testDeleteMultiLevelsLeadingToNodeBorrowRight2() throws Exception
1423 {
1424 BTree<Integer, String> btree = createMultiLevelBTreeLeavesHalfFull();
1425
1426
1427 delete( btree, EXPECTED1, 2, 3, 6, 7 );
1428
1429
1430 checkRemoval( btree, 11, EXPECTED1 );
1431
1432 btree.close();
1433 }
1434
1435
1436
1437
1438
1439
1440
1441
1442 @Test
1443 public void testDeleteMultiLevelsLeadingToNodeBorrowRight3() throws Exception
1444 {
1445 BTree<Integer, String> btree = createMultiLevelBTreeLeavesHalfFull();
1446
1447
1448 delete( btree, EXPECTED1, 2, 3, 6, 7 );
1449
1450
1451 checkRemoval( btree, 19, EXPECTED1 );
1452
1453 btree.close();
1454 }
1455
1456
1457
1458
1459
1460
1461
1462
1463 @Test
1464 public void testDeleteMultiLevelsLeadingToNodeBorrowRight4() throws Exception
1465 {
1466 BTree<Integer, String> btree = createMultiLevelBTreeLeavesHalfFull();
1467
1468
1469 delete( btree, EXPECTED1, 2, 3, 6, 7 );
1470
1471
1472 checkRemoval( btree, 14, EXPECTED1 );
1473
1474 btree.close();
1475 }
1476
1477
1478
1479
1480
1481
1482
1483
1484 @Test
1485 public void testDeleteMultiLevelsLeadingToNodeBorrowRight5() throws Exception
1486 {
1487 BTree<Integer, String> btree = createMultiLevelBTreeLeavesHalfFull();
1488
1489
1490 delete( btree, EXPECTED1, 2, 3, 6, 7 );
1491
1492
1493 checkRemoval( btree, 15, EXPECTED1 );
1494
1495 btree.close();
1496 }
1497
1498
1499
1500
1501
1502
1503
1504
1505 @Test
1506 public void testDeleteMultiLevelsLeadingToNodeBorrowLeft1() throws Exception
1507 {
1508 BTree<Integer, String> btree = createMultiLevelBTreeLeavesHalfFull();
1509
1510
1511 delete( btree, EXPECTED1, 94, 95, 98, 99 );
1512
1513
1514 checkRemoval( btree, 91, EXPECTED1 );
1515
1516 btree.close();
1517 }
1518
1519
1520
1521
1522
1523
1524
1525
1526 @Test
1527 public void testDeleteMultiLevelsLeadingToNodeBorrowLeft2() throws Exception
1528 {
1529 BTree<Integer, String> btree = createMultiLevelBTreeLeavesHalfFull();
1530
1531
1532 delete( btree, EXPECTED1, 94, 95, 98, 99 );
1533
1534
1535 checkRemoval( btree, 90, EXPECTED1 );
1536
1537 btree.close();
1538 }
1539
1540
1541
1542
1543
1544
1545
1546
1547 @Test
1548 public void testDeleteMultiLevelsLeadingToNodeBorrowLeft3() throws Exception
1549 {
1550 BTree<Integer, String> btree = createMultiLevelBTreeLeavesHalfFull();
1551
1552
1553 delete( btree, EXPECTED1, 94, 95, 98, 99 );
1554
1555
1556 checkRemoval( btree, 82, EXPECTED1 );
1557
1558 btree.close();
1559 }
1560
1561
1562
1563
1564
1565
1566
1567
1568 @Test
1569 public void testDeleteMultiLevelsLeadingToNodeBorrowLeft4() throws Exception
1570 {
1571 BTree<Integer, String> btree = createMultiLevelBTreeLeavesHalfFull();
1572
1573
1574 delete( btree, EXPECTED1, 94, 95, 98, 99 );
1575
1576
1577 checkRemoval( btree, 83, EXPECTED1 );
1578
1579 btree.close();
1580 }
1581
1582
1583
1584
1585
1586
1587
1588
1589 @Test
1590 public void testDeleteMultiLevelsLeadingToNodeBorrowLeft6() throws Exception
1591 {
1592 BTree<Integer, String> btree = createMultiLevelBTreeLeavesHalfFull();
1593
1594
1595 delete( btree, EXPECTED1, 42, 43, 46, 47 );
1596
1597
1598 checkRemoval( btree, 50, EXPECTED1 );
1599
1600 btree.close();
1601 }
1602
1603
1604
1605
1606
1607
1608
1609
1610 @Test
1611 public void testDeleteMultiLevelsLeadingToNodeBorrowLeft7() throws Exception
1612 {
1613 BTree<Integer, String> btree = createMultiLevelBTreeLeavesHalfFull();
1614
1615
1616 delete( btree, EXPECTED1, 42, 43, 46, 47 );
1617
1618
1619 checkRemoval( btree, 51, EXPECTED1 );
1620
1621 btree.close();
1622 }
1623
1624
1625
1626
1627
1628
1629
1630
1631 @Test
1632 public void testDeleteMultiLevelsLeadingToNodeBorrowLeft8() throws Exception
1633 {
1634 BTree<Integer, String> btree = createMultiLevelBTreeLeavesHalfFull();
1635
1636
1637 delete( btree, EXPECTED1, 42, 43, 46, 47 );
1638
1639
1640 checkRemoval( btree, 59, EXPECTED1 );
1641
1642 btree.close();
1643 }
1644
1645
1646
1647
1648
1649
1650
1651
1652 @Test
1653 public void testDeleteMultiLevelsLeadingToNodeBorrowLeft9() throws Exception
1654 {
1655 BTree<Integer, String> btree = createMultiLevelBTreeLeavesHalfFull();
1656
1657
1658 delete( btree, EXPECTED1, 42, 43, 46, 47 );
1659
1660
1661 checkRemoval( btree, 58, EXPECTED1 );
1662
1663 btree.close();
1664 }
1665
1666
1667
1668
1669
1670
1671
1672
1673 @Test
1674 public void testDeleteMultiLevelsLeadingToNodeBorrowLeft10() throws Exception
1675 {
1676 BTree<Integer, String> btree = createMultiLevelBTreeLeavesHalfFull();
1677
1678
1679 delete( btree, EXPECTED1, 42, 43, 46, 47 );
1680
1681
1682 checkRemoval( btree, 54, EXPECTED1 );
1683
1684 btree.close();
1685 }
1686
1687
1688
1689
1690
1691
1692
1693
1694 @Test
1695 public void testDeleteMultiLevelsLeadingToNodeBorrowLeft11() throws Exception
1696 {
1697 BTree<Integer, String> btree = createMultiLevelBTreeLeavesHalfFull();
1698
1699
1700 delete( btree, EXPECTED1, 42, 43, 46, 47 );
1701
1702
1703 checkRemoval( btree, 55, EXPECTED1 );
1704
1705 btree.close();
1706 }
1707
1708
1709
1710
1711
1712 @Test
1713 public void testAdditionNullValues() throws IOException
1714 {
1715 BTree<Integer, String> btree = createMultiLevelBTreeLeavesHalfFull();
1716
1717
1718 btree.insert( 100, null );
1719
1720 assertTrue( btree.hasKey( 100 ) );
1721
1722 try
1723 {
1724 assertNull( btree.get( 100 ) );
1725 }
1726 catch ( KeyNotFoundException knfe )
1727 {
1728 fail();
1729 }
1730
1731 Tuple<Integer, String> deleted = btree.delete( 100 );
1732
1733 assertNotNull( deleted );
1734 assertNull( deleted.getValue() );
1735 }
1736
1737
1738
1739
1740
1741
1742 @Test
1743 public void testBrowse500K() throws Exception
1744 {
1745 Random random = new Random( System.nanoTime() );
1746
1747 int nbError = 0;
1748
1749 int n = 0;
1750 int nbElems = 500000;
1751 long delta = System.currentTimeMillis();
1752
1753
1754 BTree<Long, String> btree = new BTree<Long, String>( "test", new LongSerializer(), new StringSerializer() );
1755 btree.setPageSize( 32 );
1756
1757 for ( int i = 0; i < nbElems; i++ )
1758 {
1759 Long key = ( long ) random.nextLong();
1760 String value = Long.toString( key );
1761
1762 try
1763 {
1764 btree.insert( key, value );
1765 }
1766 catch ( Exception e )
1767 {
1768 e.printStackTrace();
1769 System.out.println( btree );
1770 System.out.println( "Error while adding " + value );
1771 nbError++;
1772 return;
1773 }
1774
1775 if ( i % 100000 == 0 )
1776 {
1777 if ( n > 0 )
1778 {
1779 long t0 = System.currentTimeMillis();
1780 System.out.println( "Delta" + n + ": " + ( t0 - delta ) );
1781 delta = t0;
1782 }
1783
1784 n++;
1785 }
1786 }
1787
1788
1789 long l1 = System.currentTimeMillis();
1790
1791 Cursor<Long, String> cursor = btree.browse();
1792
1793 int nb = 0;
1794 long elem = Long.MIN_VALUE;
1795
1796 while ( cursor.hasNext() )
1797 {
1798 Tuple<Long, String> res = cursor.next();
1799
1800 if ( res.getKey() > elem )
1801 {
1802 elem = res.getKey();
1803 nb++;
1804 }
1805 }
1806
1807 System.out.println( "Nb elements read : " + nb );
1808
1809 cursor.close();
1810 btree.close();
1811
1812 long l2 = System.currentTimeMillis();
1813
1814 System.out.println( "Delta : " + ( l2 - l1 ) + ", nbError = " + nbError
1815 + ", Nb searches per second : " + ( ( nbElems * 1000 ) / ( l2 - l1 ) ) );
1816 }
1817
1818
1819 private void checkNull( BTree<Long, String> btree, long key ) throws IOException
1820 {
1821 try
1822 {
1823 btree.get( key );
1824 fail();
1825 }
1826 catch ( KeyNotFoundException knfe )
1827 {
1828
1829 }
1830 }
1831
1832
1833 private void checkNull( BTree<Integer, String> btree, int key ) throws IOException
1834 {
1835 try
1836 {
1837 btree.get( key );
1838 fail();
1839 }
1840 catch ( KeyNotFoundException knfe )
1841 {
1842
1843 }
1844 }
1845
1846
1847
1848
1849
1850 @Test
1851 public void testBrowseForwardBackwardExtremes() throws Exception
1852 {
1853
1854 BTree<Integer, String> btree = new BTree<Integer, String>( "test", new IntSerializer(), new StringSerializer() );
1855 btree.setPageSize( 4 );
1856
1857 for ( int i = 8; i < 13; i++ )
1858 {
1859 String strValue = "V" + i;
1860 btree.insert( i, strValue );
1861 }
1862
1863
1864 Cursor<Integer, String> cursor = btree.browseFrom( 8 );
1865
1866 assertTrue( cursor.hasNext() );
1867
1868
1869 assertEquals( 8, cursor.next().getKey().intValue() );
1870
1871
1872 assertEquals( 9, cursor.next().getKey().intValue() );
1873
1874
1875 assertEquals( 10, cursor.next().getKey().intValue() );
1876
1877
1878 assertEquals( 11, cursor.next().getKey().intValue() );
1879
1880
1881 assertEquals( 12, cursor.next().getKey().intValue() );
1882
1883 assertFalse( cursor.hasNext() );
1884 assertTrue( cursor.hasPrev() );
1885
1886
1887 assertEquals( 12, cursor.prev().getKey().intValue() );
1888
1889
1890 assertEquals( 11, cursor.prev().getKey().intValue() );
1891
1892
1893 assertEquals( 10, cursor.prev().getKey().intValue() );
1894
1895
1896 assertEquals( 9, cursor.prev().getKey().intValue() );
1897
1898
1899 assertEquals( 8, cursor.prev().getKey().intValue() );
1900
1901 assertFalse( cursor.hasPrev() );
1902 assertTrue( cursor.hasNext() );
1903
1904 cursor.close();
1905 btree.close();
1906 }
1907
1908
1909 @Test
1910 public void testNextAfterPrev() throws Exception
1911 {
1912 IntSerializer serializer = new IntSerializer();
1913
1914 BTreeConfiguration<Integer, Integer> config = new BTreeConfiguration<Integer, Integer>();
1915 config.setName( "master" );
1916 config.setPageSize( 4 );
1917 config.setSerializers( serializer, serializer );
1918 BTree<Integer, Integer> btree = new BTree<Integer, Integer>( config );
1919
1920 int i = 7;
1921 for ( int k = 0; k < i; k++ )
1922 {
1923 btree.insert( k, k );
1924 }
1925
1926
1927 Cursor<Integer, Integer> cursor = btree.browseFrom( 4 );
1928
1929 assertTrue( cursor.hasNext() );
1930 Tuple<Integer, Integer> tuple = cursor.next();
1931 assertEquals( Integer.valueOf( 4 ), tuple.getKey() );
1932 assertEquals( Integer.valueOf( 4 ), tuple.getValue() );
1933
1934 assertTrue( cursor.hasPrev() );
1935 tuple = cursor.prev();
1936 assertEquals( Integer.valueOf( 4 ), tuple.getKey() );
1937 assertEquals( Integer.valueOf( 4 ), tuple.getValue() );
1938
1939 assertTrue( cursor.hasNext() );
1940 tuple = cursor.next();
1941 assertEquals( Integer.valueOf( 4 ), tuple.getKey() );
1942 assertEquals( Integer.valueOf( 4 ), tuple.getValue() );
1943 cursor.close();
1944 }
1945
1946 }