View Javadoc
1   /*
2    *   Licensed to the Apache Software Foundation (ASF) under one
3    *   or more contributor license agreements.  See the NOTICE file
4    *   distributed with this work for additional information
5    *   regarding copyright ownership.  The ASF licenses this file
6    *   to you under the Apache License, Version 2.0 (the
7    *   "License"); you may not use this file except in compliance
8    *   with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *   Unless required by applicable law or agreed to in writing,
13   *   software distributed under the License is distributed on an
14   *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *   KIND, either express or implied.  See the License for the
16   *   specific language governing permissions and limitations
17   *   under the License.
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.File;
31  import java.io.IOException;
32  import java.util.NoSuchElementException;
33  import java.util.UUID;
34  
35  import org.apache.commons.io.FileUtils;
36  import org.apache.directory.mavibot.btree.exception.BTreeAlreadyManagedException;
37  import org.apache.directory.mavibot.btree.exception.DuplicateValueNotAllowedException;
38  import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
39  import org.apache.directory.mavibot.btree.serializer.IntSerializer;
40  import org.apache.directory.mavibot.btree.serializer.LongSerializer;
41  import org.apache.directory.mavibot.btree.serializer.StringSerializer;
42  import org.junit.After;
43  import org.junit.Before;
44  import org.junit.Ignore;
45  import org.junit.Rule;
46  import org.junit.Test;
47  import org.junit.rules.TemporaryFolder;
48  
49  
50  /**
51   * TODO BTreeDuplicateKeyTest.
52   *
53   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
54   */
55  public class PersistedBTreeDuplicateKeyTest
56  {
57      private BTree<Long, String> btree = null;
58  
59      private RecordManager recordManager1 = null;
60  
61      @Rule
62      public TemporaryFolder tempFolder = new TemporaryFolder();
63  
64      private File dataDir = null;
65  
66  
67      @Before
68      public void createBTree() throws IOException
69      {
70          dataDir = tempFolder.newFolder( UUID.randomUUID().toString() );
71  
72          openRecordManagerAndBtree();
73  
74          try
75          {
76              // Create a new BTree
77              btree = recordManager1.addBTree( "test", LongSerializer.INSTANCE, StringSerializer.INSTANCE,
78                  BTree.ALLOW_DUPLICATES );
79          }
80          catch ( Exception e )
81          {
82              throw new RuntimeException( e );
83          }
84      }
85  
86  
87      @After
88      public void cleanup() throws IOException
89      {
90          dataDir = new File( System.getProperty( "java.io.tmpdir" ) + "/recordman" );
91  
92          btree.close();
93  
94          if ( dataDir.exists() )
95          {
96              FileUtils.deleteDirectory( dataDir );
97          }
98          
99          recordManager1.close();
100         assertTrue( recordManager1.isContextOk() );
101     }
102 
103 
104     private void openRecordManagerAndBtree()
105     {
106         try
107         {
108             if ( recordManager1 != null )
109             {
110                 recordManager1.close();
111             }
112 
113             // Now, try to reload the file back
114             recordManager1 = new RecordManager( dataDir.getAbsolutePath() );
115 
116             // load the last created btree
117             if ( btree != null )
118             {
119                 btree = recordManager1.getManagedTree( btree.getName() );
120             }
121         }
122         catch ( Exception e )
123         {
124             throw new RuntimeException( e );
125         }
126     }
127 
128 
129     @Test
130     public void testInsertNullValue() throws IOException, KeyNotFoundException
131     {
132         btree.insert( 1L, null );
133 
134         TupleCursor<Long, String> cursor = btree.browse();
135         assertTrue( cursor.hasNext() );
136 
137         Tuple<Long, String> t = cursor.next();
138 
139         assertEquals( Long.valueOf( 1 ), t.getKey() );
140         assertEquals( null, t.getValue() );
141 
142         cursor.close();
143 
144         btree.close();
145     }
146 
147 
148     @Test
149     public void testBrowseEmptyTree() throws IOException, KeyNotFoundException, BTreeAlreadyManagedException
150     {
151         IntSerializer serializer = IntSerializer.INSTANCE;
152 
153         BTree<Integer, Integer> btree = BTreeFactory.createPersistedBTree( "master", serializer, serializer );
154         
155         // Inject the newly created BTree into teh recordManager
156         recordManager1.manage( btree );
157 
158         TupleCursor<Integer, Integer> cursor = btree.browse();
159         assertFalse( cursor.hasNext() );
160         assertFalse( cursor.hasPrev() );
161 
162         try
163         {
164             cursor.next();
165             fail( "Should not reach here" );
166         }
167         catch ( NoSuchElementException e )
168         {
169             assertTrue( true );
170         }
171 
172         try
173         {
174             cursor.prev();
175             fail( "Should not reach here" );
176         }
177         catch ( NoSuchElementException e )
178         {
179             assertTrue( true );
180         }
181 
182         cursor.close();
183         btree.close();
184     }
185 
186 
187     @Test
188     public void testDuplicateKey() throws IOException, KeyNotFoundException
189     {
190         btree.insert( 1L, "1" );
191         btree.insert( 1L, "2" );
192 
193         TupleCursor<Long, String> cursor = btree.browse();
194         assertTrue( cursor.hasNext() );
195 
196         Tuple<Long, String> t = cursor.next();
197 
198         assertEquals( Long.valueOf( 1 ), t.getKey() );
199         assertEquals( "1", t.getValue() );
200 
201         assertTrue( cursor.hasNext() );
202 
203         t = cursor.next();
204 
205         assertEquals( Long.valueOf( 1 ), t.getKey() );
206         assertEquals( "2", t.getValue() );
207 
208         assertFalse( cursor.hasNext() );
209 
210         // test backward move
211         assertTrue( cursor.hasPrev() );
212 
213         t = cursor.prev();
214 
215         assertEquals( Long.valueOf( 1 ), t.getKey() );
216         assertEquals( "1", t.getValue() );
217 
218         assertFalse( cursor.hasPrev() );
219 
220         // again forward
221         assertTrue( cursor.hasNext() );
222 
223         t = cursor.next();
224 
225         assertEquals( Long.valueOf( 1 ), t.getKey() );
226         assertEquals( "2", t.getValue() );
227 
228         assertFalse( cursor.hasNext() );
229 
230         cursor.close();
231         btree.close();
232     }
233 
234 
235     @Test
236     public void testGetDuplicateKey() throws Exception
237     {
238         String retVal = btree.insert( 1L, "1" );
239         assertNull( retVal );
240 
241         retVal = btree.insert( 1L, "2" );
242         assertNull( retVal );
243 
244         // check the return value when an existing value is added again
245         retVal = btree.insert( 1L, "2" );
246         assertEquals( "2", retVal );
247 
248         assertEquals( "1", btree.get( 1L ) );
249         assertTrue( btree.contains( 1L, "1" ) );
250         assertTrue( btree.contains( 1L, "2" ) );
251 
252         assertFalse( btree.contains( 1L, "0" ) );
253         assertFalse( btree.contains( 0L, "1" ) );
254         assertFalse( btree.contains( 0L, "0" ) );
255         assertFalse( btree.contains( null, "0" ) );
256         assertFalse( btree.contains( 0L, null ) );
257         assertFalse( btree.contains( null, null ) );
258         btree.close();
259     }
260 
261 
262     @Test
263     public void testRemoveDuplicateKey() throws Exception
264     {
265         btree.insert( 1L, "1" );
266         btree.insert( 1L, "2" );
267 
268         assertEquals( 2, btree.getNbElems() );
269 
270         Tuple<Long, String> t = btree.delete( 1L, "1" );
271         assertEquals( Long.valueOf( 1 ), t.getKey() );
272         assertEquals( "1", t.getValue() );
273 
274         assertEquals( 1l, btree.getNbElems() );
275 
276         t = btree.delete( 1L, "2" );
277         assertEquals( Long.valueOf( 1 ), t.getKey() );
278         assertEquals( "2", t.getValue() );
279 
280         assertEquals( 0l, btree.getNbElems() );
281 
282         t = btree.delete( 1L, "2" );
283         assertNull( t );
284         btree.close();
285     }
286 
287 
288     @Test
289     public void testFullPage() throws Exception
290     {
291         int i = 7;
292         for ( char ch = 'a'; ch <= 'z'; ch++ )
293         {
294             for ( int k = 0; k < i; k++ )
295             {
296                 String val = ch + Integer.toString( k );
297                 btree.insert( Long.valueOf( ch ), val );
298             }
299         }
300 
301         TupleCursor<Long, String> cursor = btree.browse();
302 
303         char ch = 'a';
304         int k = 0;
305 
306         while ( cursor.hasNext() )
307         {
308             Tuple<Long, String> t = cursor.next();
309             assertEquals( Long.valueOf( ch ), t.getKey() );
310             k++;
311 
312             if ( ( k % i ) == 0 )
313             {
314                 ch++;
315             }
316         }
317 
318         assertEquals( ( 'z' + 1 ), ch );
319 
320         ch = 'z';
321         cursor.afterLast();
322 
323         while ( cursor.hasPrev() )
324         {
325             Tuple<Long, String> t = cursor.prev();
326             assertEquals( Long.valueOf( ch ), t.getKey() );
327             k--;
328 
329             if ( ( k % i ) == 0 )
330             {
331                 ch--;
332             }
333         }
334 
335         assertEquals( ( 'a' - 1 ), ch );
336         cursor.close();
337     }
338 
339 
340     @Test
341     public void testMoveFirst() throws Exception
342     {
343         for ( char ch = 'a'; ch <= 'z'; ch++ )
344         {
345             String val = Character.toString( ch );
346             btree.insert( Long.valueOf( ch ), val );
347         }
348 
349         assertEquals( 26, btree.getNbElems() );
350 
351         // add one more value for 'a'
352         btree.insert( Long.valueOf( 'a' ), "val" );
353 
354         assertEquals( 27, btree.getNbElems() );
355 
356         // Start from c : we should have only 24 values
357         TupleCursor<Long, String> cursor = btree.browseFrom( Long.valueOf( 'c' ) );
358 
359         int i = 0;
360 
361         while ( cursor.hasNext() )
362         {
363             Tuple<Long, String> tuple = cursor.next();
364             assertNotNull( tuple );
365             i++;
366         }
367 
368         assertEquals( 24, i );
369 
370         // now move the cursor first
371         cursor.beforeFirst();
372         assertTrue( cursor.hasNext() );
373         Tuple<Long, String> tuple = cursor.next();
374 
375         // We should be on the first position
376         assertEquals( Long.valueOf( 'a' ), tuple.getKey() );
377 
378         // Count the number of element after the first one, we should have 26 only
379         i = 0;
380 
381         while ( cursor.hasNext() )
382         {
383             tuple = cursor.next();
384             assertNotNull( tuple );
385             i++;
386         }
387 
388         assertEquals( 26, i );
389 
390         cursor.close();
391 
392         // Rebrowse
393         cursor = btree.browse();
394 
395         i = 0;
396 
397         while ( cursor.hasNext() )
398         {
399             assertNotNull( cursor.next() );
400             i++;
401         }
402 
403         // again, we should see 27 elements
404         assertEquals( 27, i );
405 
406         // now move the cursor first, but move forward the keys
407         cursor.beforeFirst();
408         assertTrue( cursor.hasNextKey() );
409         assertEquals( Long.valueOf( 'a' ), cursor.nextKey().getKey() );
410 
411         i = 0;
412 
413         while ( cursor.hasNextKey() )
414         {
415             tuple = cursor.nextKey();
416             long key = tuple.getKey();
417             assertNotNull( key );
418             i++;
419         }
420 
421         // We should have 25 keys only, as we just moved forward the first one
422         assertEquals( 25, i );
423     }
424 
425 
426     @Test
427     public void testMoveLast() throws Exception
428     {
429         for ( char ch = 'a'; ch <= 'z'; ch++ )
430         {
431             String val = Character.toString( ch );
432             btree.insert( Long.valueOf( ch ), val );
433         }
434 
435         assertEquals( 26, btree.getNbElems() );
436 
437         // add one more value for 'z'
438         btree.insert( Long.valueOf( 'z' ), "val" );
439 
440         assertEquals( 27, btree.getNbElems() );
441 
442         // Start from x : we should have only 23 values
443         TupleCursor<Long, String> cursor = btree.browseFrom( Long.valueOf( 'x' ) );
444 
445         int i = 0;
446 
447         while ( cursor.hasPrev() )
448         {
449             Tuple<Long, String> tuple = cursor.prev();
450             assertNotNull( tuple );
451             i++;
452         }
453 
454         assertEquals( 23, i );
455 
456         // now move the cursor to the last element
457         cursor.afterLast();
458         assertTrue( cursor.hasPrev() );
459         Tuple<Long, String> tuple = cursor.prev();
460 
461         // We should be on the last position
462         assertEquals( Long.valueOf( 'z' ), tuple.getKey() );
463 
464         // Count the number of element before the last one, we should have 26
465         i = 0;
466 
467         while ( cursor.hasPrev() )
468         {
469             tuple = cursor.prev();
470             assertNotNull( tuple );
471             i++;
472         }
473 
474         assertEquals( 26, i );
475 
476         cursor.close();
477 
478         // Rebrowse
479         cursor = btree.browse();
480         cursor.afterLast();
481 
482         i = 0;
483 
484         while ( cursor.hasPrev() )
485         {
486             assertNotNull( cursor.prev() );
487             i++;
488         }
489 
490         // again, we should see 27 elements
491         assertEquals( 27, i );
492 
493         // now move the cursor first, but move backward the keys
494         cursor.afterLast();
495         assertTrue( cursor.hasPrevKey() );
496         assertEquals( Long.valueOf( 'z' ), cursor.prevKey().getKey() );
497 
498         i = 0;
499 
500         while ( cursor.hasPrevKey() )
501         {
502             tuple = cursor.prevKey();
503             long key = tuple.getKey();
504             assertNotNull( key );
505             i++;
506         }
507 
508         // We should have 25 keys only, as we just moved forward the first one
509         assertEquals( 25, i );
510     }
511 
512 
513     @Test(expected = NoSuchElementException.class)
514     public void testMoveLast2() throws Exception
515     {
516         for ( char ch = 'a'; ch <= 'z'; ch++ )
517         {
518             btree.insert( Long.valueOf( ch ), UUID.randomUUID().toString() );
519         }
520 
521         btree.insert( Long.valueOf( 'z' ), UUID.randomUUID().toString() );
522 
523         TupleCursor<Long, String> cursor = btree.browseFrom( Long.valueOf( 'c' ) );
524         cursor.afterLast();
525 
526         assertFalse( cursor.hasNext() );
527         assertTrue( cursor.hasPrev() );
528         assertEquals( Long.valueOf( 'z' ), cursor.prev().getKey() );
529         // the key, 'z', has two values
530         assertEquals( Long.valueOf( 'z' ), cursor.prev().getKey() );
531         assertEquals( Long.valueOf( 'y' ), cursor.prev().getKey() );
532 
533         cursor.beforeFirst();
534         assertEquals( Long.valueOf( 'a' ), cursor.next().getKey() );
535 
536         cursor.afterLast();
537         assertFalse( cursor.hasNext() );
538         // make sure it throws NoSuchElementException
539         cursor.next();
540     }
541 
542 
543     @Test(expected = NoSuchElementException.class)
544     public void testNextPrevKey() throws Exception
545     {
546         int i = 7;
547 
548         // Insert keys from a to z with 7 values for each key
549         for ( char ch = 'a'; ch <= 'z'; ch++ )
550         {
551             for ( int k = 0; k < i; k++ )
552             {
553                 btree.insert( Long.valueOf( ch ), String.valueOf( k ) );
554             }
555         }
556 
557         TupleCursor<Long, String> cursor = btree.browse();
558 
559         assertTrue( cursor.hasNext() );
560         assertFalse( cursor.hasPrev() );
561 
562         for ( int k = 0; k < 2; k++ )
563         {
564             assertEquals( Long.valueOf( 'a' ), cursor.next().getKey() );
565         }
566 
567         assertEquals( Long.valueOf( 'a' ), cursor.next().getKey() );
568 
569         Tuple<Long, String> tuple = cursor.nextKey();
570 
571         assertEquals( Long.valueOf( 'b' ), tuple.getKey() );
572 
573         for ( char ch = 'b'; ch < 'z'; ch++ )
574         {
575             assertEquals( Long.valueOf( ch ), cursor.next().getKey() );
576             tuple = cursor.nextKey();
577             char t = ch;
578             assertEquals( Long.valueOf( ++t ), tuple.getKey() );
579         }
580 
581         for ( int k = 0; k < i; k++ )
582         {
583             assertEquals( Long.valueOf( 'z' ), cursor.next().getKey() );
584         }
585 
586         assertFalse( cursor.hasNextKey() );
587         assertTrue( cursor.hasPrevKey() );
588         tuple = cursor.prev();
589         assertEquals( Long.valueOf( 'z' ), tuple.getKey() );
590         assertEquals( "6", tuple.getValue() );
591 
592         for ( char ch = 'z'; ch > 'a'; ch-- )
593         {
594             char t = ch;
595             t--;
596 
597             assertEquals( Long.valueOf( ch ), cursor.prev().getKey() );
598 
599             tuple = cursor.prevKey();
600 
601             assertEquals( Long.valueOf( t ), tuple.getKey() );
602         }
603 
604         for ( int k = 5; k >= 0; k-- )
605         {
606             tuple = cursor.prev();
607             assertEquals( Long.valueOf( 'a' ), tuple.getKey() );
608             assertEquals( String.valueOf( k ), tuple.getValue() );
609         }
610 
611         assertTrue( cursor.hasNext() );
612         assertFalse( cursor.hasPrev() );
613         tuple = cursor.next();
614         assertEquals( Long.valueOf( 'a' ), tuple.getKey() );
615         assertEquals( "0", tuple.getValue() );
616 
617         cursor.close();
618 
619         cursor = btree.browseFrom( Long.valueOf( 'y' ) );
620         tuple = cursor.prevKey();
621         assertNotNull( tuple );
622         assertEquals( Long.valueOf( 'y' ), tuple.getKey() );
623         assertEquals( "6", tuple.getValue() );
624         cursor.close();
625 
626         cursor = btree.browse();
627         cursor.beforeFirst();
628         assertFalse( cursor.hasPrev() );
629         // make sure it throws NoSuchElementException
630         cursor.prev();
631     }
632 
633 
634     /**
635      * Test for moving between two leaves. When moveToNextNonDuplicateKey is called
636      * and cursor is on the last element of the current leaf.
637      *
638      * @throws Exception
639      */
640     @Test
641     public void testMoveToNextAndPrevWithPageBoundaries() throws Exception
642     {
643         int i = 32;
644         for ( int k = 0; k < i; k++ )
645         {
646             btree.insert( ( long ) k, Long.toString( k ) );
647         }
648 
649         // 15 is the last element of the first leaf
650         // Check that we correctly jump to the next page
651         TupleCursor<Long, String> cursor = btree.browseFrom( 15L );
652         Tuple<Long, String> tuple = cursor.nextKey();
653 
654         assertNotNull( tuple );
655         assertEquals( Long.valueOf( 16 ), tuple.getKey() );
656         assertEquals( "16", tuple.getValue() );
657         cursor.close();
658 
659         // Do the same check, on the revert side : moving backward
660         cursor = btree.browseFrom( 16L );
661         tuple = cursor.prevKey();
662 
663         assertNotNull( tuple );
664         assertEquals( Long.valueOf( 15 ), tuple.getKey() );
665         assertEquals( "15", tuple.getValue() );
666         cursor.close();
667 
668         // Now do a next followed by a prev on the boundary of 2 pages
669         cursor = btree.browseFrom( 16L );
670         tuple = cursor.prevKey();
671 
672         assertNotNull( tuple );
673         assertEquals( Long.valueOf( 15 ), tuple.getKey() );
674         assertEquals( "15", tuple.getValue() );
675 
676         // Move next, we should be back to the initial value
677         assertTrue( cursor.hasNext() );
678         tuple = cursor.next();
679         assertEquals( Long.valueOf( 16 ), tuple.getKey() );
680         assertEquals( "16", tuple.getValue() );
681         cursor.close();
682 
683         // test the extremes of the BTree instead of that of leaves
684         cursor = btree.browseFrom( 30L );
685         tuple = cursor.nextKey();
686         assertFalse( cursor.hasNext() );
687         assertTrue( cursor.hasPrev() );
688 
689         assertEquals( Long.valueOf( 31 ), tuple.getKey() );
690         assertEquals( "31", tuple.getValue() );
691         cursor.close();
692 
693         cursor = btree.browse();
694         assertTrue( cursor.hasNext() );
695         assertFalse( cursor.hasPrev() );
696 
697         tuple = cursor.nextKey();
698         assertEquals( Long.valueOf( 0 ), tuple.getKey() );
699         assertEquals( "0", tuple.getValue() );
700         cursor.close();
701     }
702 
703 
704     @Test
705     public void testNextAfterPrev() throws Exception
706     {
707         int i = 32;
708 
709         for ( int k = 0; k < i; k++ )
710         {
711             btree.insert( ( long ) k, String.valueOf( k ) );
712         }
713 
714         // 15 is the last element of the first leaf
715         TupleCursor<Long, String> cursor = btree.browseFrom( 16L );
716 
717         assertTrue( cursor.hasNext() );
718         Tuple<Long, String> tuple = cursor.next();
719         assertEquals( Long.valueOf( 16 ), tuple.getKey() );
720         assertEquals( "16", tuple.getValue() );
721 
722         assertTrue( cursor.hasPrev() );
723         tuple = cursor.prev();
724         assertEquals( Long.valueOf( 15 ), tuple.getKey() );
725         assertEquals( "15", tuple.getValue() );
726 
727         assertTrue( cursor.hasNext() );
728         tuple = cursor.next();
729         assertEquals( Long.valueOf( 16 ), tuple.getKey() );
730         assertEquals( "16", tuple.getValue() );
731         cursor.close();
732 
733     }
734 
735 
736     /**
737      * Test for moving after a key and traversing backwards.
738      *
739      * @throws Exception
740      */
741     @Test
742     public void testMoveToNextAndTraverseBackward() throws Exception
743     {
744         int i = 5;
745 
746         for ( int k = 0; k < i; k++ )
747         {
748             btree.insert( ( long ) k, Long.toString( k ) );
749         }
750 
751         // 4 is the last element in the tree
752         TupleCursor<Long, String> cursor = btree.browseFrom( 4L );
753         cursor.nextKey();
754 
755         long currentKey = 4L;
756 
757         while ( cursor.hasPrev() )
758         {
759             assertEquals( Long.valueOf( currentKey ), cursor.prev().getKey() );
760             currentKey--;
761         }
762 
763         cursor.close();
764     }
765 
766 
767     /**
768      * Test for moving after a key and traversing backwards.
769      *
770      * @throws Exception
771      */
772     @Test
773     public void testMoveToPrevAndTraverseForward() throws Exception
774     {
775         int i = 5;
776 
777         for ( int k = 0; k < i; k++ )
778         {
779             btree.insert( ( long ) k, Long.toString( k ) );
780         }
781 
782         // 4 is the last element in the tree
783         TupleCursor<Long, String> cursor = btree.browseFrom( 0L );
784 
785         long currentKey = 0L;
786 
787         while ( cursor.hasNext() )
788         {
789             assertEquals( Long.valueOf( currentKey ), cursor.next().getKey() );
790             currentKey++;
791         }
792 
793         cursor.close();
794     }
795 
796     
797     @Test
798     public void testFindLeftAndRightMosetInSubBTree() throws Exception
799     {
800         PersistedBTreeConfiguration<Integer, Integer> config = new PersistedBTreeConfiguration<Integer, Integer>();
801 
802         config.setName( "test" );
803         config.setKeySerializer( IntSerializer.INSTANCE );
804         config.setValueSerializer( IntSerializer.INSTANCE );
805         config.setAllowDuplicates( false );
806         config.setBtreeType( BTreeTypeEnum.PERSISTED_SUB );
807 
808         PersistedBTree<Integer, Integer> subBtree = new PersistedBTree<Integer, Integer>( config );
809         
810         subBtree.setRecordManager( recordManager1 );
811         
812         subBtree.insert( 1, 1 ); // the values will be discarded in this BTree type
813         subBtree.insert( 2, 2 );
814         subBtree.insert( 3, 3 );
815         subBtree.insert( 4, 4 );
816         subBtree.insert( 5, 5 );
817         
818         Tuple<Integer, Integer> t = subBtree.getRootPage().findLeftMost();
819         assertEquals( Integer.valueOf( 1 ), t.getKey() );
820         
821         t = subBtree.getRootPage().findRightMost();
822         assertEquals( Integer.valueOf( 5 ), t.getKey() );
823     }
824 
825     /**
826      * Test that a BTree which forbid duplicate values does not accept them
827      */
828     @Test(expected = DuplicateValueNotAllowedException.class)
829     @Ignore("this condition is removed")
830     public void testBTreeForbidDups() throws IOException, BTreeAlreadyManagedException
831     {
832         BTree<Long, String> singleValueBtree = recordManager1.addBTree( "test2", LongSerializer.INSTANCE,
833             StringSerializer.INSTANCE, BTree.FORBID_DUPLICATES );
834 
835         for ( long i = 0; i < 64; i++ )
836         {
837             singleValueBtree.insert( i, Long.toString( i ) );
838         }
839 
840         try
841         {
842             singleValueBtree.insert( 18L, "Duplicate" );
843             fail();
844         }
845         finally
846         {
847             singleValueBtree.close();
848         }
849     }
850 }