/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 *
 */
package org.apache.directory.mavibot.btree;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import org.apache.commons.io.FileUtils;
import org.apache.directory.mavibot.btree.exception.BTreeAlreadyManagedException;
import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
import org.apache.directory.mavibot.btree.serializer.LongSerializer;
import org.apache.directory.mavibot.btree.serializer.StringSerializer;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;


/**
 * test the RecordManager
 *
 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
 */
public class RecordManagerTest
{
    private BTree<Long, String> btree = null;

    private RecordManager recordManager = null;

    @Rule
    public TemporaryFolder tempFolder = new TemporaryFolder();

    private File dataDir = null;


    @Before
    public void createBTree()
    {
        dataDir = tempFolder.newFolder( UUID.randomUUID().toString() );

        System.out.println( dataDir + "/mavibot.db" );

        openRecordManagerAndBtree();

        try
        {
            // Create a new BTree
            btree = recordManager.addBTree( "test", LongSerializer.INSTANCE, StringSerializer.INSTANCE, false );
        }
        catch ( Exception e )
        {
            throw new RuntimeException( e );
        }
    }


    @After
    public void cleanup() throws IOException
    {
        btree.close();

        if ( dataDir.exists() )
        {
            FileUtils.deleteDirectory( dataDir );
        }
    }


    private void openRecordManagerAndBtree()
    {
        try
        {
            if ( recordManager != null )
            {
                recordManager.close();
            }

            // Now, try to reload the file back
            recordManager = new RecordManager( dataDir.getAbsolutePath() );

            // load the last created btree
            if ( btree != null )
            {
                btree = recordManager.getManagedTree( btree.getName() );
            }
        }
        catch ( Exception e )
        {
            throw new RuntimeException( e );
        }
    }


    /**
     * Test the creation of a RecordManager, and that we can read it back.
     */
    @Test
    public void testRecordManager() throws IOException, BTreeAlreadyManagedException
    {
        assertEquals( 1, recordManager.getNbManagedTrees() );

        Set<String> managedBTrees = recordManager.getManagedTrees();

        assertEquals( 1, managedBTrees.size() );
        assertTrue( managedBTrees.contains( "test" ) );

        BTree<Long, String> btree1 = recordManager.getManagedTree( "test" );

        assertNotNull( btree1 );
        assertEquals( btree.getComparator().getClass().getName(), btree1.getComparator().getClass().getName() );
        assertEquals( btree.getKeySerializer().getClass().getName(), btree1.getKeySerializer().getClass().getName() );
        assertEquals( btree.getName(), btree1.getName() );
        assertEquals( btree.getNbElems(), btree1.getNbElems() );
        assertEquals( btree.getPageSize(), btree1.getPageSize() );
        assertEquals( btree.getRevision(), btree1.getRevision() );
        assertEquals( btree.getValueSerializer().getClass().getName(), btree1.getValueSerializer().getClass().getName() );
    }


    /**
     * Test the creation of a RecordManager with a BTree containing data.
     */
    @Test
    public void testRecordManagerWithBTree() throws IOException, BTreeAlreadyManagedException, KeyNotFoundException
    {
        // Now, add some elements in the BTree
        btree.insert( 3L, "V3" );
        btree.insert( 1L, "V1" );
        btree.insert( 5L, "V5" );

        // Now, try to reload the file back
        openRecordManagerAndBtree();

        assertEquals( 1, recordManager.getNbManagedTrees() );

        Set<String> managedBTrees = recordManager.getManagedTrees();

        assertEquals( 1, managedBTrees.size() );
        assertTrue( managedBTrees.contains( "test" ) );

        BTree<Long, String> btree1 = recordManager.getManagedTree( "test" );

        assertNotNull( btree1 );
        assertEquals( btree.getComparator().getClass().getName(), btree1.getComparator().getClass().getName() );
        assertEquals( btree.getKeySerializer().getClass().getName(), btree1.getKeySerializer().getClass().getName() );
        assertEquals( btree.getName(), btree1.getName() );
        assertEquals( btree.getNbElems(), btree1.getNbElems() );
        assertEquals( btree.getPageSize(), btree1.getPageSize() );
        assertEquals( btree.getRevision(), btree1.getRevision() );
        assertEquals( btree.getValueSerializer().getClass().getName(), btree1.getValueSerializer().getClass().getName() );

        // Check the stored element
        assertTrue( btree1.hasKey( 1L ) );
        assertTrue( btree1.hasKey( 3L ) );
        assertTrue( btree1.hasKey( 5L ) );
        assertEquals( "V1", btree1.get( 1L ) );
        assertEquals( "V3", btree1.get( 3L ) );
        assertEquals( "V5", btree1.get( 5L ) );
    }


    /**
     * Test the creation of a RecordManager with a BTree containing data, enough for some Node to be created.
     */
    @Test
    public void testRecordManagerWithBTreeLeafNode() throws IOException, BTreeAlreadyManagedException,
        KeyNotFoundException
    {
        // Now, add some elements in the BTree
        for ( long i = 1L; i < 32L; i++ )
        {
            btree.insert( i, "V" + i );
        }

        // Now, try to reload the file back
        openRecordManagerAndBtree();

        assertEquals( 1, recordManager.getNbManagedTrees() );

        Set<String> managedBTrees = recordManager.getManagedTrees();

        assertEquals( 1, managedBTrees.size() );
        assertTrue( managedBTrees.contains( "test" ) );

        BTree<Long, String> btree1 = recordManager.getManagedTree( "test" );

        assertNotNull( btree1 );
        assertEquals( btree.getComparator().getClass().getName(), btree1.getComparator().getClass().getName() );
        assertEquals( btree.getKeySerializer().getClass().getName(), btree1.getKeySerializer().getClass().getName() );
        assertEquals( btree.getName(), btree1.getName() );
        assertEquals( btree.getNbElems(), btree1.getNbElems() );
        assertEquals( btree.getPageSize(), btree1.getPageSize() );
        assertEquals( btree.getRevision(), btree1.getRevision() );
        assertEquals( btree.getValueSerializer().getClass().getName(), btree1.getValueSerializer().getClass().getName() );

        // Check the stored element
        for ( long i = 1L; i < 32L; i++ )
        {
            assertTrue( btree1.hasKey( i ) );
            assertEquals( "V" + i, btree1.get( i ) );
        }
    }


    /**
     * Test the creation of a RecordManager with a BTree containing 100 000 elements
     */
    @Test
    @Ignore("This is a performance test")
    public void testRecordManagerWithBTreeLeafNode100K() throws IOException, BTreeAlreadyManagedException,
        KeyNotFoundException
    {
        // Don't keep any revision
        recordManager.setKeepRevisions( false );

        String fileName = dataDir.getAbsolutePath() + "/mavibot.db";
        File file = new File( fileName );
        long fileSize = file.length();
        long nbElems = 100000L;
        System.out.println( "----- Size before = " + fileSize );

        // Now, add some elements in the BTree
        long t0 = System.currentTimeMillis();

        for ( Long i = 0L; i < nbElems; i++ )
        {
            String value = "V" + i;
            btree.insert( i, value );

            /*
            if ( !recordManager1.check() )
            {
                System.out.println( "Failure while adding element " + i );
                fail();
            }
            */

            if ( i % 10000 == 0 )
            {
                fileSize = file.length();
                System.out.println( "----- Size after insertion of " + i + " = " + fileSize );
                System.out.println( recordManager );
                //System.out.println( btree );
            }
        }
        long t1 = System.currentTimeMillis();

        fileSize = file.length();
        System.out.println( "Size after insertion of 100 000 elements : " + fileSize );
        System.out.println( "Time taken to write 100 000 elements : " + ( t1 - t0 ) );
        System.out.println( "  Nb elem/s : " + ( ( nbElems * 1000 ) / ( t1 - t0 ) ) );
        System.out.println( "Nb created page " + recordManager.nbCreatedPages.get() );
        System.out.println( "Nb allocated page " + recordManager.nbReusedPages.get() );
        System.out.println( "Nb page we have freed " + recordManager.nbFreedPages.get() );
        System.out.println( recordManager );

        // Now, try to reload the file back
        openRecordManagerAndBtree();

        assertEquals( 1, recordManager.getNbManagedTrees() );

        Set<String> managedBTrees = recordManager.getManagedTrees();

        assertEquals( 1, managedBTrees.size() );
        assertTrue( managedBTrees.contains( "test" ) );

        BTree<Long, String> btree1 = recordManager.getManagedTree( "test" );

        assertNotNull( btree1 );
        assertEquals( btree.getComparator().getClass().getName(), btree1.getComparator().getClass().getName() );
        assertEquals( btree.getKeySerializer().getClass().getName(), btree1.getKeySerializer().getClass().getName() );
        assertEquals( btree.getName(), btree1.getName() );
        assertEquals( btree.getNbElems(), btree1.getNbElems() );
        assertEquals( btree.getPageSize(), btree1.getPageSize() );
        assertEquals( btree.getRevision(), btree1.getRevision() );
        assertEquals( btree.getValueSerializer().getClass().getName(), btree1.getValueSerializer().getClass().getName() );

        // Check the stored element
        long t2 = System.currentTimeMillis();
        for ( long i = 0L; i < nbElems; i++ )
        {
            //assertTrue( btree1.exist( i ) );
            assertEquals( "V" + i, btree1.get( i ) );
        }
        long t3 = System.currentTimeMillis();
        System.out.println( "Time taken to verify 100 000 elements : " + ( t3 - t2 ) );

        // Check the stored element a second time
        long t4 = System.currentTimeMillis();
        for ( long i = 0L; i < nbElems; i++ )
        {
            //assertTrue( btree1.exist( i ) );
            assertEquals( "V" + i, btree1.get( i ) );
        }
        long t5 = System.currentTimeMillis();
        System.out.println( "Time taken to verify 100 000 elements : " + ( t5 - t4 ) );
    }


    private void checkBTreeRevisionBrowse( BTree<Long, String> btree, long revision, long... values )
        throws IOException,
        KeyNotFoundException
    {
        TupleCursor<Long, String> cursor = btree.browse( revision );
        List<Long> expected = new ArrayList<Long>( values.length );
        Set<Long> found = new HashSet<Long>( values.length );

        for ( long value : values )
        {
            expected.add( value );
        }

        int nb = 0;

        while ( cursor.hasNext() )
        {
            Tuple<Long, String> res = cursor.next();

            long key = res.getKey();
            assertEquals( expected.get( nb ), ( Long ) key );
            assertFalse( found.contains( key ) );
            found.add( key );
            assertEquals( "V" + key, res.getValue() );
            nb++;
        }

        assertEquals( values.length, nb );
        cursor.close();
    }


    private void checkBTreeRevisionBrowseFrom( BTree<Long, String> btree, long revision, long from, long... values )
        throws IOException,
        KeyNotFoundException
    {
        TupleCursor<Long, String> cursor = btree.browseFrom( revision, from );
        List<Long> expected = new ArrayList<Long>( values.length );
        Set<Long> found = new HashSet<Long>( values.length );

        for ( long value : values )
        {
            expected.add( value );
        }

        int nb = 0;

        while ( cursor.hasNext() )
        {
            Tuple<Long, String> res = cursor.next();

            long key = res.getKey();
            assertEquals( expected.get( nb ), ( Long ) key );
            assertFalse( found.contains( key ) );
            found.add( key );
            assertEquals( "V" + key, res.getValue() );
            nb++;
        }

        assertEquals( values.length, nb );
        cursor.close();

    }


    /**
     * Test the creation of a RecordManager with a BTree containing data, where we keep the revisions,
     * and browse the BTree.
     */
    @Test
    public void testRecordManagerBrowseWithKeepRevisions() throws IOException, BTreeAlreadyManagedException,
        KeyNotFoundException
    {
        recordManager.setKeepRevisions( true );

        // Now, add some elements in the BTree
        btree.insert( 3L, "V3" );
        long rev1 = btree.getRevision();

        btree.insert( 1L, "V1" );
        long rev2 = btree.getRevision();

        btree.insert( 5L, "V5" );
        long rev3 = btree.getRevision();

        // Check that we can browse each revision
        // revision 1
        checkBTreeRevisionBrowse( btree, rev1, 3L );

        // Revision 2
        checkBTreeRevisionBrowse( btree, rev2, 1L, 3L );

        // Revision 3
        checkBTreeRevisionBrowse( btree, rev3, 1L, 3L, 5L );

        // Now, try to reload the file back
        openRecordManagerAndBtree();

        assertEquals( 1, recordManager.getNbManagedTrees() );

        Set<String> managedBTrees = recordManager.getManagedTrees();

        assertEquals( 1, managedBTrees.size() );
        assertTrue( managedBTrees.contains( "test" ) );

        BTree<Long, String> btree1 = recordManager.getManagedTree( "test" );

        assertNotNull( btree1 );
        assertEquals( btree.getComparator().getClass().getName(), btree1.getComparator().getClass().getName() );
        assertEquals( btree.getKeySerializer().getClass().getName(), btree1.getKeySerializer().getClass().getName() );
        assertEquals( btree.getName(), btree1.getName() );
        assertEquals( btree.getNbElems(), btree1.getNbElems() );
        assertEquals( btree.getPageSize(), btree1.getPageSize() );
        assertEquals( btree.getRevision(), btree1.getRevision() );
        assertEquals( btree.getValueSerializer().getClass().getName(), btree1.getValueSerializer().getClass().getName() );

        // Check the stored element
        assertTrue( btree1.hasKey( 1L ) );
        assertTrue( btree1.hasKey( 3L ) );
        assertTrue( btree1.hasKey( 5L ) );
        assertEquals( "V1", btree1.get( 1L ) );
        assertEquals( "V3", btree1.get( 3L ) );
        assertEquals( "V5", btree1.get( 5L ) );

        // Check that we can read the revision again
        // revision 1
        checkBTreeRevisionBrowse( btree, rev1 );

        // Revision 2
        checkBTreeRevisionBrowse( btree, rev2 );

        // Revision 3
        checkBTreeRevisionBrowse( btree, rev3, 1L, 3L, 5L );
    }


    /**
     * Test the creation of a RecordManager with a BTree containing data, where we keep the revision, and
     * we browse from a key
     */
    @Test
    public void testRecordManagerBrowseFromWithRevision() throws IOException, BTreeAlreadyManagedException,
        KeyNotFoundException
    {
        recordManager.setKeepRevisions( true );

        // Now, add some elements in the BTree
        btree.insert( 3L, "V3" );
        long rev1 = btree.getRevision();

        btree.insert( 1L, "V1" );
        long rev2 = btree.getRevision();

        btree.insert( 5L, "V5" );
        long rev3 = btree.getRevision();

        // Check that we can browse each revision
        // revision 1
        checkBTreeRevisionBrowseFrom( btree, rev1, 3L, 3L );

        // Revision 2
        checkBTreeRevisionBrowseFrom( btree, rev2, 3L, 3L );

        // Revision 3
        checkBTreeRevisionBrowseFrom( btree, rev3, 3L, 3L, 5L );

        // Now, try to reload the file back
        openRecordManagerAndBtree();

        assertEquals( 1, recordManager.getNbManagedTrees() );

        Set<String> managedBTrees = recordManager.getManagedTrees();

        assertEquals( 1, managedBTrees.size() );
        assertTrue( managedBTrees.contains( "test" ) );

        BTree<Long, String> btree1 = recordManager.getManagedTree( "test" );

        assertNotNull( btree1 );
        assertEquals( btree.getComparator().getClass().getName(), btree1.getComparator().getClass().getName() );
        assertEquals( btree.getKeySerializer().getClass().getName(), btree1.getKeySerializer().getClass().getName() );
        assertEquals( btree.getName(), btree1.getName() );
        assertEquals( btree.getNbElems(), btree1.getNbElems() );
        assertEquals( btree.getPageSize(), btree1.getPageSize() );
        assertEquals( btree.getRevision(), btree1.getRevision() );
        assertEquals( btree.getValueSerializer().getClass().getName(), btree1.getValueSerializer().getClass().getName() );

        // Check the stored element
        assertTrue( btree1.hasKey( 1L ) );
        assertTrue( btree1.hasKey( 3L ) );
        assertTrue( btree1.hasKey( 5L ) );
        assertEquals( "V1", btree1.get( 1L ) );
        assertEquals( "V3", btree1.get( 3L ) );
        assertEquals( "V5", btree1.get( 5L ) );

        // Check that we can read the revision again
        // revision 1
        checkBTreeRevisionBrowseFrom( btree, rev1, 3L );

        // Revision 2
        checkBTreeRevisionBrowseFrom( btree, rev2, 3L );

        // Revision 3
        checkBTreeRevisionBrowseFrom( btree, rev3, 3L, 3L, 5L );
    }


    /**
     * Test a get() from a given revision
     */
    @Test
    public void testGetWithRevision() throws IOException, BTreeAlreadyManagedException,
        KeyNotFoundException
    {
        recordManager.setKeepRevisions( true );

        // Now, add some elements in the BTree
        btree.insert( 3L, "V3" );
        long rev1 = btree.getRevision();

        btree.insert( 1L, "V1" );
        long rev2 = btree.getRevision();

        btree.insert( 5L, "V5" );
        long rev3 = btree.getRevision();

        // Delete one element
        btree.delete( 3L );
        long rev4 = btree.getRevision();

        // Check that we can get a value from each revision
        // revision 1
        assertEquals( "V3", btree.get( rev1, 3L ) );

        // revision 2
        assertEquals( "V1", btree.get( rev2, 1L ) );
        assertEquals( "V3", btree.get( rev2, 3L ) );

        // revision 3
        assertEquals( "V1", btree.get( rev3, 1L ) );
        assertEquals( "V3", btree.get( rev3, 3L ) );
        assertEquals( "V5", btree.get( rev3, 5L ) );

        // revision 4
        assertEquals( "V1", btree.get( rev4, 1L ) );
        assertEquals( "V5", btree.get( rev4, 5L ) );

        try
        {
            btree.get( rev4, 3L );
            fail();
        }
        catch ( KeyNotFoundException knfe )
        {
            // expected
        }

        // Now, try to reload the file back
        openRecordManagerAndBtree();

        assertEquals( 1, recordManager.getNbManagedTrees() );

        Set<String> managedBTrees = recordManager.getManagedTrees();

        assertEquals( 1, managedBTrees.size() );
        assertTrue( managedBTrees.contains( "test" ) );

        BTree<Long, String> btree1 = recordManager.getManagedTree( "test" );

        assertNotNull( btree1 );
        assertEquals( btree.getComparator().getClass().getName(), btree1.getComparator().getClass().getName() );
        assertEquals( btree.getKeySerializer().getClass().getName(), btree1.getKeySerializer().getClass().getName() );
        assertEquals( btree.getName(), btree1.getName() );
        assertEquals( btree.getNbElems(), btree1.getNbElems() );
        assertEquals( btree.getPageSize(), btree1.getPageSize() );
        assertEquals( btree.getRevision(), btree1.getRevision() );
        assertEquals( btree.getValueSerializer().getClass().getName(), btree1.getValueSerializer().getClass().getName() );

        // Check the stored element
        assertTrue( btree1.hasKey( 1L ) );
        assertFalse( btree1.hasKey( 3L ) );
        assertTrue( btree1.hasKey( 5L ) );
        assertEquals( "V1", btree1.get( 1L ) );
        assertEquals( "V5", btree1.get( 5L ) );

        // Check that we can get a value from each revision
        // revision 1
        checkBTreeRevisionBrowse( btree, rev1 );

        // revision 2
        checkBTreeRevisionBrowse( btree, rev2 );

        // revision 3
        checkBTreeRevisionBrowse( btree, rev3 );

        // revision 4
        checkBTreeRevisionBrowse( btree, rev4, 1L, 5L );

        try
        {
            btree.get( rev4, 3L );
            fail();
        }
        catch ( KeyNotFoundException knfe )
        {
            // expected
        }
    }


    /**
     * Test a contain() from a given revision
     */
    @Test
    public void testContainWithRevision() throws IOException, BTreeAlreadyManagedException,
        KeyNotFoundException
    {
        recordManager.setKeepRevisions( true );

        // Now, add some elements in the BTree
        btree.insert( 3L, "V3" );
        long rev1 = btree.getRevision();

        btree.insert( 1L, "V1" );
        long rev2 = btree.getRevision();

        btree.insert( 5L, "V5" );
        long rev3 = btree.getRevision();

        // Delete one element
        btree.delete( 3L );
        long rev4 = btree.getRevision();

        // Check that we can get a value from each revision
        // revision 1
        assertFalse( btree.contains( rev1, 1L, "V1" ) );
        assertTrue( btree.contains( rev1, 3L, "V3" ) );
        assertFalse( btree.contains( rev1, 5L, "V5" ) );

        // revision 2
        assertTrue( btree.contains( rev2, 1L, "V1" ) );
        assertTrue( btree.contains( rev2, 3L, "V3" ) );
        assertFalse( btree.contains( rev2, 5L, "V5" ) );

        // revision 3
        assertTrue( btree.contains( rev3, 1L, "V1" ) );
        assertTrue( btree.contains( rev3, 3L, "V3" ) );
        assertTrue( btree.contains( rev3, 5L, "V5" ) );

        // revision 4
        assertTrue( btree.contains( rev4, 1L, "V1" ) );
        assertFalse( btree.contains( rev4, 3L, "V3" ) );
        assertTrue( btree.contains( rev4, 5L, "V5" ) );

        // Now, try to reload the file back
        openRecordManagerAndBtree();

        assertEquals( 1, recordManager.getNbManagedTrees() );

        Set<String> managedBTrees = recordManager.getManagedTrees();

        assertEquals( 1, managedBTrees.size() );
        assertTrue( managedBTrees.contains( "test" ) );

        BTree<Long, String> btree1 = recordManager.getManagedTree( "test" );

        assertNotNull( btree1 );
        assertEquals( btree.getComparator().getClass().getName(), btree1.getComparator().getClass().getName() );
        assertEquals( btree.getKeySerializer().getClass().getName(), btree1.getKeySerializer().getClass().getName() );
        assertEquals( btree.getName(), btree1.getName() );
        assertEquals( btree.getNbElems(), btree1.getNbElems() );
        assertEquals( btree.getPageSize(), btree1.getPageSize() );
        assertEquals( btree.getRevision(), btree1.getRevision() );
        assertEquals( btree.getValueSerializer().getClass().getName(), btree1.getValueSerializer().getClass().getName() );

        // Check the stored element
        assertTrue( btree1.hasKey( 1L ) );
        assertFalse( btree1.hasKey( 3L ) );
        assertTrue( btree1.hasKey( 5L ) );
        assertEquals( "V1", btree1.get( 1L ) );
        assertEquals( "V5", btree1.get( 5L ) );

        // Check that we can get a value from each revision
        // revision 1
        assertFalse( btree.contains( rev1, 1L, "V1" ) );
        assertFalse( btree.contains( rev1, 3L, "V3" ) );
        assertFalse( btree.contains( rev1, 5L, "V5" ) );

        // revision 2
        assertFalse( btree.contains( rev2, 1L, "V1" ) );
        assertFalse( btree.contains( rev2, 3L, "V3" ) );
        assertFalse( btree.contains( rev2, 5L, "V5" ) );

        // revision 3
        assertFalse( btree.contains( rev3, 1L, "V1" ) );
        assertFalse( btree.contains( rev3, 3L, "V3" ) );
        assertFalse( btree.contains( rev3, 5L, "V5" ) );

        // revision 4
        assertTrue( btree.contains( rev4, 1L, "V1" ) );
        assertFalse( btree.contains( rev4, 3L, "V3" ) );
        assertTrue( btree.contains( rev4, 5L, "V5" ) );
    }


    /**
     * Test a hasKey() from a given revision
     */
    @Test
    public void testHasKeyWithRevision() throws IOException, BTreeAlreadyManagedException,
        KeyNotFoundException
    {
        recordManager.setKeepRevisions( true );

        // Now, add some elements in the BTree
        btree.insert( 3L, "V3" );
        long rev1 = btree.getRevision();

        btree.insert( 1L, "V1" );
        long rev2 = btree.getRevision();

        btree.insert( 5L, "V5" );
        long rev3 = btree.getRevision();

        // Delete one element
        btree.delete( 3L );
        long rev4 = btree.getRevision();

        // Check that we can get a value from each revision
        // revision 1
        assertFalse( btree.hasKey( rev1, 1L ) );
        assertTrue( btree.hasKey( rev1, 3L ) );
        assertFalse( btree.hasKey( rev1, 5L ) );

        // revision 2
        assertTrue( btree.hasKey( rev2, 1L ) );
        assertTrue( btree.hasKey( rev2, 3L ) );
        assertFalse( btree.hasKey( rev2, 5L ) );

        // revision 3
        assertTrue( btree.hasKey( rev3, 1L ) );
        assertTrue( btree.hasKey( rev3, 3L ) );
        assertTrue( btree.hasKey( rev3, 5L ) );

        // revision 4
        assertTrue( btree.hasKey( rev4, 1L ) );
        assertFalse( btree.hasKey( rev4, 3L ) );
        assertTrue( btree.hasKey( rev4, 5L ) );

        // Now, try to reload the file back
        openRecordManagerAndBtree();

        assertEquals( 1, recordManager.getNbManagedTrees() );

        Set<String> managedBTrees = recordManager.getManagedTrees();

        assertEquals( 1, managedBTrees.size() );
        assertTrue( managedBTrees.contains( "test" ) );

        BTree<Long, String> btree1 = recordManager.getManagedTree( "test" );

        assertNotNull( btree1 );
        assertEquals( btree.getComparator().getClass().getName(), btree1.getComparator().getClass().getName() );
        assertEquals( btree.getKeySerializer().getClass().getName(), btree1.getKeySerializer().getClass().getName() );
        assertEquals( btree.getName(), btree1.getName() );
        assertEquals( btree.getNbElems(), btree1.getNbElems() );
        assertEquals( btree.getPageSize(), btree1.getPageSize() );
        assertEquals( btree.getRevision(), btree1.getRevision() );
        assertEquals( btree.getValueSerializer().getClass().getName(), btree1.getValueSerializer().getClass().getName() );

        // Check the stored element
        assertTrue( btree1.hasKey( 1L ) );
        assertFalse( btree1.hasKey( 3L ) );
        assertTrue( btree1.hasKey( 5L ) );
        assertEquals( "V1", btree1.get( 1L ) );
        assertEquals( "V5", btree1.get( 5L ) );

        // Check that we can get a value from each revision
        // revision 1
        assertFalse( btree.hasKey( rev1, 1L ) );
        assertFalse( btree.hasKey( rev1, 3L ) );
        assertFalse( btree.hasKey( rev1, 5L ) );

        // revision 2
        assertFalse( btree.hasKey( rev2, 1L ) );
        assertFalse( btree.hasKey( rev2, 3L ) );
        assertFalse( btree.hasKey( rev2, 5L ) );

        // revision 3
        assertFalse( btree.hasKey( rev3, 1L ) );
        assertFalse( btree.hasKey( rev3, 3L ) );
        assertFalse( btree.hasKey( rev3, 5L ) );

        // revision 4
        assertTrue( btree.hasKey( rev4, 1L ) );
        assertFalse( btree.hasKey( rev4, 3L ) );
        assertTrue( btree.hasKey( rev4, 5L ) );
    }


    /**
     * Test with BTrees containing duplicate keys
     */
    @Test
    public void testBTreesDuplicateKeys() throws IOException, BTreeAlreadyManagedException,
        KeyNotFoundException
    {
        int pageSize = 16;
        int numKeys = 1;
        String name = "duplicateTree";
        String[] testValues = new String[]
            { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F", "10" };

        BTree<Long, String> dupsTree = BTreeFactory.createPersistedBTree( name, LongSerializer.INSTANCE,
            StringSerializer.INSTANCE, pageSize, true );

        recordManager.manage( dupsTree );

        for ( long i = 0; i < numKeys; i++ )
        {
            for ( int k = 0; k < pageSize + 1; k++ )
            {
                dupsTree.insert( i, testValues[k] );
            }
        }

        // Now, try to reload the file back
        openRecordManagerAndBtree();

        dupsTree = recordManager.getManagedTree( name );

        for ( long i = 0; i < numKeys; i++ )
        {
            ValueCursor<String> values = dupsTree.getValues( i );

            for ( int k = 0; k < pageSize + 1; k++ )
            {
                assertTrue( values.next().equals( testValues[k] ) );
            }
        }
    }
}
