You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2009/08/05 19:55:16 UTC

svn commit: r801340 [11/13] - in /directory/apacheds/trunk: core-entry/src/main/java/org/apache/directory/server/core/entry/ core-entry/src/test/java/org/apache/directory/server/core/entry/ core-integ/src/main/java/org/apache/directory/server/core/inte...

Modified: directory/apacheds/trunk/jdbm-store/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/DupsCursorTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/jdbm-store/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/DupsCursorTest.java?rev=801340&r1=801339&r2=801340&view=diff
==============================================================================
--- directory/apacheds/trunk/jdbm-store/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/DupsCursorTest.java (original)
+++ directory/apacheds/trunk/jdbm-store/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/DupsCursorTest.java Wed Aug  5 17:55:15 2009
@@ -1,1284 +1,1284 @@
-/*
- * 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.server.core.partition.impl.btree.jdbm;
-
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.apache.directory.server.xdbm.Table;
-import org.apache.directory.server.xdbm.Tuple;
-import org.apache.directory.server.schema.SerializableComparator;
-import org.apache.directory.shared.ldap.cursor.Cursor;
-import org.apache.directory.shared.ldap.cursor.InvalidCursorPositionException;
-import org.junit.Before;
-import org.junit.After;
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-import java.io.File;
-
-import jdbm.RecordManager;
-import jdbm.helper.IntegerSerializer;
-import jdbm.recman.BaseRecordManager;
-
-
-/**
- * Tests the Cursor functionality of a JdbmTable when duplicate keys are 
- * supported.
- *
- * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
- * @version $Rev$, $Date$
- */
-public class DupsCursorTest
-{
-    private static final Logger LOG = LoggerFactory.getLogger( DupsCursorTest.class.getSimpleName() );
-    private static final String TEST_OUTPUT_PATH = "test.output.path";
-    private static final int SIZE = 15;
-
-    transient Table<Integer,Integer> table;
-    transient File dbFile;
-    transient RecordManager recman;
-
-
-    @Before
-    public void createTable() throws Exception
-    {
-        File tmpDir = null;
-        if ( System.getProperty( TEST_OUTPUT_PATH, null ) != null )
-        {
-            tmpDir = new File( System.getProperty( TEST_OUTPUT_PATH ) );
-        }
-
-        dbFile = File.createTempFile( getClass().getSimpleName(), "db", tmpDir );
-        recman = new BaseRecordManager( dbFile.getAbsolutePath() );
-
-        // gosh this is a terrible use of a global static variable
-        SerializableComparator.setRegistry( new MockComparatorRegistry() );
-
-        table = new JdbmTable<Integer,Integer>( "test", SIZE, recman,
-                new SerializableComparator<Integer>( "" ),
-                new SerializableComparator<Integer>( "" ),
-                null, new IntegerSerializer() );
-        LOG.debug( "Created new table and populated it with data" );
-    }
-
-
-    @After
-    public void destryTable() throws Exception
-    {
-        table.close();
-        table = null;
-        recman.close();
-        recman = null;
-        dbFile.deleteOnExit();
-        // Remove temporary files
-        String fileToDelete = dbFile.getAbsolutePath();
-        new File( fileToDelete ).delete();
-        new File( fileToDelete + ".db" ).delete();
-        new File( fileToDelete + ".lg" ).delete();
-        
-        dbFile = null;
-    }
-
-
-    @Test
-    public void testEmptyTableOperations() throws Exception
-    {
-        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
-        assertFalse( cursor.next() );
-        
-        cursor.afterLast();
-        assertFalse( cursor.previous() );
-
-        cursor.beforeFirst();
-        assertFalse( cursor.next() );
-
-        assertFalse( cursor.first() );
-        assertFalse( cursor.last() );
-    }
-
-
-    @Test
-    public void testNextNoDups() throws Exception
-    {
-        // first try without duplicates at all
-        for ( int ii = 0; ii < SIZE-1; ii++ )
-        {
-            table.put( ii, ii );
-        }
-        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
-
-        int ii = 0;
-        while ( cursor.next() )
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            assertEquals( ii, ( int ) tuple.getKey() );
-            assertEquals( ii, ( int ) tuple.getValue() );
-            ii++;
-        }
-    }
-
-
-    @Test
-    public void testPreviousNoDups() throws Exception
-    {
-        for ( int ii = 0; ii < SIZE-1; ii++ )
-        {
-            table.put( ii, ii );
-        }
-        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
-
-        int ii = SIZE-2;
-        while ( cursor.previous() )
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            assertEquals( ii, ( int ) tuple.getKey() );
-            assertEquals( ii, ( int ) tuple.getValue() );
-            ii--;
-        }
-    }
-
-
-    @Test
-    public void testNextDups() throws Exception
-    {
-        for ( int ii = 0; ii < SIZE*3; ii++ )
-        {
-            if ( ii > 12 && ii < 17 + SIZE )
-            {
-                table.put( 13, ii );
-            }
-            else
-            {
-                table.put( ii, ii );
-            }
-        }
-        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
-
-        int ii = 0;
-        while ( cursor.next() )
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 12 && ii < 17 + SIZE )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-    }
-
-
-    @Test
-    public void testPreviousDups() throws Exception
-    {
-        for ( int ii = 0; ii < SIZE*3; ii++ )
-        {
-            if ( ii > 12 && ii < 17 + SIZE )
-            {
-                table.put( 13, ii );
-            }
-            else
-            {
-                table.put( ii, ii );
-            }
-        }
-        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
-        cursor.afterLast();
-
-        int ii = SIZE*3 - 1;
-        while ( cursor.previous() )
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 12 && ii < 17 + SIZE )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii--;
-        }
-    }
-
-
-    @Test
-    public void testFirstLastUnderDupLimit() throws Exception
-    {
-        for ( int ii = 0; ii < SIZE*2 - 1; ii++ )
-        {
-            if ( ii > 12 && ii < 17 )
-            {
-                table.put( 13, ii );
-            }
-            else
-            {
-                table.put( ii, ii );
-            }
-        }
-        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
-
-        int ii = 0;
-        while ( cursor.next() )
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 12 && ii < 17 )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-
-        cursor.first();
-        ii = 0;
-        do
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 12 && ii < 17 )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-        while ( cursor.next() );
-
-        // now go backwards
-        cursor.afterLast();
-        ii = SIZE*2-2;
-        while ( cursor.previous() )
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 12 && ii < 17 )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii--;
-        }
-
-        // now advance to last and go backwards again
-        cursor.last();
-        ii = SIZE*2-2;
-        do
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 12 && ii < 17 )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii--;
-        }
-        while ( cursor.previous() );
-
-        // advance to first then last and go backwards again
-        cursor.beforeFirst();
-        cursor.afterLast();
-        ii = SIZE*2-2;
-        while ( cursor.previous() )
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 12 && ii < 17 )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii--;
-        }
-    }
-
-
-    @Test
-    public void testFirstLastOverDupLimit() throws Exception
-    {
-        for ( int ii = 0; ii < SIZE*3-1; ii++ )
-        {
-            if ( ii < 2 + SIZE ) // keys with multiple values
-            {
-                table.put( 0, ii );
-            }
-            else // keys with single values
-            {
-                table.put( ii, ii );
-            }
-        }
-        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
-
-        int ii = 0;
-        while ( cursor.next() )
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii < 2 + SIZE )
-            {
-                assertEquals( 0, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-
-        // now go back to first and traverse all over again
-        cursor.first();
-        ii = 0;
-        do
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii < 2 + SIZE )
-            {
-                assertEquals( 0, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-        while ( cursor.next() );
-
-        // now go backwards
-        cursor.afterLast();
-        ii = SIZE*3-2;
-        while ( cursor.previous() )
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-
-            if ( ii < 2 + SIZE )
-            {
-                assertEquals( 0, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii--;
-        }
-
-        // now advance to last and go backwards again
-        cursor.last();
-        ii = SIZE*3-2;
-        do
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii < 2 + SIZE )
-            {
-                assertEquals( 0, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii--;
-        }
-        while ( cursor.previous() );
-
-        // advance to first then last and go backwards again
-        cursor.beforeFirst();
-        cursor.afterLast();
-        ii = SIZE*3-2;
-        while ( cursor.previous() )
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii < 2 + SIZE )
-            {
-                assertEquals( 0, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii--;
-        }
-    }
-
-
-    @Test
-    public void testFirstOverDupLimit() throws Exception
-    {
-        for ( int ii = 0; ii < SIZE*3-1; ii++ )
-        {
-            if ( ii < 2 + SIZE ) // keys with multiple values
-            {
-                table.put( 0, ii );
-            }
-            else // keys with single values
-            {
-                table.put( ii, ii );
-            }
-        }
-        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
-
-        int ii = 0;
-        while ( cursor.next() )
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii < 2 + SIZE )
-            {
-                assertEquals( 0, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-
-        // now go back to first and traverse all over again
-        cursor.first();
-        ii = 0;
-        do
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii < 2 + SIZE )
-            {
-                assertEquals( 0, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-        while ( cursor.next() );
-
-        // now go backwards
-        cursor.afterLast();
-        ii = SIZE*3-2;
-        while ( cursor.previous() )
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-
-            if ( ii < 2 + SIZE )
-            {
-                assertEquals( 0, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii--;
-        }
-
-        // now advance to last and go backwards again
-        cursor.last();
-        ii = SIZE*3-2;
-        do
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii < 2 + SIZE )
-            {
-                assertEquals( 0, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii--;
-        }
-        while ( cursor.previous() );
-
-        // advance to first then last and go backwards again
-        cursor.beforeFirst();
-        cursor.afterLast();
-        ii = SIZE*3-2;
-        while ( cursor.previous() )
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii < 2 + SIZE )
-            {
-                assertEquals( 0, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii--;
-        }
-    }
-
-
-
-
-    @Test
-    public void testLastOverDupLimit() throws Exception
-    {
-        for ( int ii = 0; ii < SIZE*3-1; ii++ )
-        {
-            if ( ii > 2 + SIZE ) // keys with multiple values
-            {
-                table.put( 3 + SIZE, ii );
-            }
-            else // keys with single values
-            {
-                table.put( ii, ii );
-            }
-        }
-        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
-
-        int ii = 0;
-        while ( cursor.next() )
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 2 + SIZE )
-            {
-                assertEquals( 3 + SIZE, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-
-        // now go back to first and traverse all over again
-        cursor.first();
-        ii = 0;
-        do
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 2 + SIZE )
-            {
-                assertEquals( 3 + SIZE, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-        while ( cursor.next() );
-
-        // now go backwards
-        cursor.afterLast();
-        ii = SIZE*3-2;
-        while ( cursor.previous() )
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-
-            if ( ii > 2 + SIZE )
-            {
-                assertEquals( 3 + SIZE, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii--;
-        }
-
-        // now advance to last and go backwards again
-        cursor.last();
-        ii = SIZE*3-2;
-        do
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 2 + SIZE )
-            {
-                assertEquals( 3 + SIZE, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii--;
-        }
-        while ( cursor.previous() );
-
-        // advance to first then last and go backwards again
-        cursor.beforeFirst();
-        cursor.afterLast();
-        ii = SIZE*3-2;
-        while ( cursor.previous() )
-        {
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 2 + SIZE )
-            {
-                assertEquals( 3 + SIZE, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii--;
-        }
-    }
-
-
-    @Test
-    public void testOnEmptyTable() throws Exception
-    {
-        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
-        assertNotNull( cursor );
-        assertFalse( cursor.isClosed() );
-        
-        cursor.before( new Tuple<Integer, Integer>( 1, 2 ) );
-        assertFalse( cursor.available() );
-    }
-
-    
-    @Test
-    public void testOverDupLimit() throws Exception
-    {
-        table.put( 5, 5 );
-        table.put( 6, 6 );
-        for ( int ii = 0; ii < 20; ii++ )
-        {
-            table.put( 7, ii );
-        }
-        table.put( 8, 8 );
-        table.put( 9, 9 );
-        
-        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
-        assertNotNull( cursor );
-        assertFalse( cursor.isClosed() );
-        
-        cursor.before( new Tuple<Integer, Integer>( 7, 2 ) );
-        assertFalse( cursor.available() );
-    }
-
-    
-    @Test
-    public void testUnderDupLimit() throws Exception
-    {
-        table.put( 5, 5 );
-        table.put( 6, 6 );
-        for ( int ii = 0; ii < 10; ii++ )
-        {
-            table.put( 7, ii );
-        }
-        table.put( 8, 8 );
-        table.put( 9, 9 );
-        
-        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
-        assertNotNull( cursor );
-        assertFalse( cursor.isClosed() );
-        
-        cursor.before( new Tuple<Integer, Integer>( 7, 2 ) );
-        assertFalse( cursor.available() );
-    }
-
-
-    @Test
-    public void testBeforeAfterBelowDupLimit() throws Exception
-    {
-        for ( int ii = 0; ii < SIZE*2 - 1; ii++ )
-        {
-            if ( ii > 12 && ii < 17 ) // keys with multiple values
-            {
-                table.put( 13, ii );
-            }
-            else if ( ii > 17 && ii < 21 ) // adds hole with no keys for ii
-            {
-            }
-            else // keys with single values
-            {
-                table.put( ii, ii );
-            }
-        }
-
-        // test before to advance just before a key with a single value
-        int ii = 5;
-        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
-        cursor.before( new Tuple<Integer,Integer>( 5, 5 ) );
-        while ( cursor.next() )
-        {
-            if ( ii > 17 && ii < 21 )
-            {
-                assertFalse( table.has( ii ) );
-                continue;
-            }
-
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 12 && ii < 17 )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-
-        // test before to advance just before a key with a single value but
-        // with a null tuple value which should not advance the dupsCursor
-        ii = 5;
-        cursor = table.cursor();
-        cursor.before( new Tuple<Integer,Integer>( 5, null ) );
-        while ( cursor.next() )
-        {
-            if ( ii > 17 && ii < 21 )
-            {
-                assertFalse( table.has( ii ) );
-                continue;
-            }
-
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 12 && ii < 17 )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-
-        // test before to advance just before a key value pair where the key
-        // does not exist - using value so we hit check for key equality
-        ii = 21;
-        cursor = table.cursor();
-        cursor.before( new Tuple<Integer,Integer>( 18, 18 ) );
-        while ( cursor.next() )
-        {
-            if ( ii > 17 && ii < 21 )
-            {
-                assertFalse( table.has( ii ) );
-                continue;
-            }
-
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 12 && ii < 17 )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-
-        // test after to advance just after the end
-        cursor = table.cursor();
-        cursor.after( new Tuple<Integer,Integer>( 111, null ) );
-        assertFalse( cursor.next() );
-
-        // test after to advance just before a key with a single value
-        ii = 6;
-        cursor = table.cursor();
-        cursor.after( new Tuple<Integer,Integer>( 5, null ) );
-        while ( cursor.next() )
-        {
-            if ( ii > 17 && ii < 21 )
-            {
-                assertFalse( table.has( ii ) );
-                continue;
-            }
-
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 12 && ii < 17 )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-
-        // test before to advance just before a key & value with multiple
-        // values for the key - we should advance just before the value
-        cursor = table.cursor();
-        cursor.before( new Tuple<Integer,Integer>( 13, 14 ) );
-
-        cursor.next();
-        Tuple<Integer,Integer> tuple = cursor.get();
-        assertEquals( 13, ( int ) tuple.getKey() );
-        assertEquals( 14, ( int ) tuple.getValue() );
-        ii = 15;
-
-        while ( cursor.next() )
-        {
-            if ( ii > 17 && ii < 21 )
-            {
-                assertFalse( table.has( ii ) );
-                continue;
-            }
-
-            tuple = cursor.get();
-            if ( ii > 12 && ii < 17 )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-
-        // test after to advance just before a key & value with multiple
-        // values for the key - we should advance just before the value
-        cursor = table.cursor();
-        cursor.after( new Tuple<Integer,Integer>( 13, 14 ) );
-
-        cursor.next();
-        tuple = cursor.get();
-        assertEquals( 13, ( int ) tuple.getKey() );
-        assertEquals( 15, ( int ) tuple.getValue() );
-        ii=16;
-
-        while ( cursor.next() )
-        {
-            if ( ii > 17 && ii < 21 )
-            {
-                assertFalse( table.has( ii ) );
-                continue;
-            }
-
-            tuple = cursor.get();
-            if ( ii > 12 && ii < 17 )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-
-        // test after to advance just before a key that does not exist
-        cursor = table.cursor();
-        cursor.after( new Tuple<Integer,Integer>( 18, null ) );
-
-        cursor.next();
-        tuple = cursor.get();
-        assertEquals( 21, ( int ) tuple.getKey() );
-        assertEquals( 21, ( int ) tuple.getValue() );
-        ii=22;
-
-        while ( cursor.next() )
-        {
-            if ( ii > 17 && ii < 21 )
-            {
-                assertFalse( table.has( ii ) );
-                continue;
-            }
-
-            tuple = cursor.get();
-            if ( ii > 12 && ii < 17 )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-
-        // test after to advance just before a key and value where the key
-        // does not exist - used to force key comparison in after()
-        cursor = table.cursor();
-        cursor.after( new Tuple<Integer,Integer>( 18, 18 ) );
-
-        cursor.next();
-        tuple = cursor.get();
-        assertEquals( 21, ( int ) tuple.getKey() );
-        assertEquals( 21, ( int ) tuple.getValue() );
-        ii=22;
-
-        while ( cursor.next() )
-        {
-            if ( ii > 17 && ii < 21 )
-            {
-                assertFalse( table.has( ii ) );
-                continue;
-            }
-
-            tuple = cursor.get();
-            if ( ii > 12 && ii < 17 )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-    }
-
-
-    @Test
-    public void testBeforeAfterOverDupLimit() throws Exception
-    {
-        for ( int ii = 0; ii < SIZE*3 - 1; ii++ )
-        {
-            if ( ii > 12 && ii < 17 + SIZE ) // keys with multiple values
-            {
-                table.put( 13, ii );
-            }
-            else if ( ii > 17 + SIZE  && ii < 21 + SIZE ) // adds hole with no keys for ii
-            {
-            }
-            else // keys with single values
-            {
-                table.put( ii, ii );
-            }
-        }
-
-        // test before to advance just before a key with a single value
-        int ii = 5;
-        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
-        cursor.before( new Tuple<Integer,Integer>( 5, 5 ) );
-        while ( cursor.next() )
-        {
-            if ( ii > 17 + SIZE && ii < 21 + SIZE )
-            {
-                assertFalse( table.has( ii ) );
-                continue;
-            }
-
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 12 && ii < 17 + SIZE )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-
-        // test before to advance just before a key with a single value but
-        // with a null tuple value which should not advance the dupsCursor
-        ii = 5;
-        cursor = table.cursor();
-        cursor.before( new Tuple<Integer,Integer>( 5, null ) );
-        while ( cursor.next() )
-        {
-            if ( ii > 17 + SIZE && ii < 21 + SIZE )
-            {
-                assertFalse( table.has( ii ) );
-                continue;
-            }
-
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 12 && ii < 17 + SIZE )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-
-        // test before to advance just before a key value pair where the key
-        // does not exist - using value so we hit check for key equality
-        ii = 21 + SIZE;
-        cursor = table.cursor();
-        cursor.before( new Tuple<Integer,Integer>( 18 + SIZE, 18 + SIZE ) );
-        while ( cursor.next() )
-        {
-            if ( ii > 17 + SIZE && ii < 21 + SIZE )
-            {
-                assertFalse( table.has( ii ) );
-                continue;
-            }
-
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 12 && ii < 17 + SIZE )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-
-        // test after to advance just after the end
-        cursor = table.cursor();
-        cursor.after( new Tuple<Integer,Integer>( 111, null ) );
-        assertFalse( cursor.next() );
-
-        // test after to advance just before a key with a single value
-        ii = 6;
-        cursor = table.cursor();
-        cursor.after( new Tuple<Integer,Integer>( 5, null ) );
-        while ( cursor.next() )
-        {
-            if ( ii > 17 + SIZE && ii < 21 + SIZE )
-            {
-                assertFalse( table.has( ii ) );
-                continue;
-            }
-
-            Tuple<Integer,Integer> tuple = cursor.get();
-            if ( ii > 12 && ii < 17 + SIZE )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-
-        // test before to advance just before a key & value with multiple
-        // values for the key - we should advance just before the value
-        cursor = table.cursor();
-        cursor.before( new Tuple<Integer,Integer>( 13, 14 ) );
-
-        cursor.next();
-        Tuple<Integer,Integer> tuple = cursor.get();
-        assertEquals( 13, ( int ) tuple.getKey() );
-        assertEquals( 14, ( int ) tuple.getValue() );
-        ii = 15;
-
-        while ( cursor.next() )
-        {
-            if ( ii > 17 + SIZE && ii < 21 + SIZE )
-            {
-                assertFalse( table.has( ii ) );
-                continue;
-            }
-
-            tuple = cursor.get();
-            if ( ii > 12 && ii < 17 + SIZE )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-
-        // test after to advance just before a key & value with multiple
-        // values for the key - we should advance just before the value
-        cursor = table.cursor();
-        cursor.after( new Tuple<Integer,Integer>( 13, 14 ) );
-
-        cursor.next();
-        tuple = cursor.get();
-        assertEquals( 13, ( int ) tuple.getKey() );
-        assertEquals( 15, ( int ) tuple.getValue() );
-        ii=16;
-
-        while ( cursor.next() )
-        {
-            if ( ii > 17 + SIZE && ii < 21 + SIZE )
-            {
-                assertFalse( table.has( ii ) );
-                continue;
-            }
-
-            tuple = cursor.get();
-            if ( ii > 12 && ii < 17 + SIZE )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-
-        // test after to advance just before a key that does not exist
-        cursor = table.cursor();
-        cursor.after( new Tuple<Integer,Integer>( 18 + SIZE, null ) );
-
-        cursor.next();
-        tuple = cursor.get();
-        assertEquals( 21 + SIZE, ( int ) tuple.getKey() );
-        assertEquals( 21 + SIZE, ( int ) tuple.getValue() );
-        ii=22 + SIZE;
-
-        while ( cursor.next() )
-        {
-            if ( ii > 17 + SIZE && ii < 21 + SIZE )
-            {
-                assertFalse( table.has( ii ) );
-                continue;
-            }
-
-            tuple = cursor.get();
-            if ( ii > 12 && ii < 17 + SIZE )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-
-        // test after to advance just before a key and value where the key
-        // does not exist - used to force key comparison in after()
-        cursor = table.cursor();
-        cursor.after( new Tuple<Integer,Integer>( 18 + SIZE , 18 + SIZE ) );
-
-        cursor.next();
-        tuple = cursor.get();
-        assertEquals( 21 + SIZE, ( int ) tuple.getKey() );
-        assertEquals( 21 + SIZE, ( int ) tuple.getValue() );
-        ii=22+ SIZE;
-
-        while ( cursor.next() )
-        {
-            if ( ii > 17 + SIZE && ii < 21 + SIZE )
-            {
-                assertFalse( table.has( ii ) );
-                continue;
-            }
-
-            tuple = cursor.get();
-            if ( ii > 12 && ii < 17 + SIZE )
-            {
-                assertEquals( 13, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            else
-            {
-                assertEquals( ii, ( int ) tuple.getKey() );
-                assertEquals( ii, ( int ) tuple.getValue() );
-            }
-            ii++;
-        }
-    }
-
-
-    @Test
-    public void testMiscellaneous() throws Exception
-    {
-        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
-        assertNotNull( cursor );
-        assertTrue( cursor.isElementReused() );
-
-        try
-        {
-            cursor.get();
-            fail( "Should never get here due to invalid cursor position exception." );
-        }
-        catch( InvalidCursorPositionException e )
-        {
-        }
-    }
-}
+/*
+ * 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.server.core.partition.impl.btree.jdbm;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.directory.server.xdbm.Table;
+import org.apache.directory.server.xdbm.Tuple;
+import org.apache.directory.server.schema.SerializableComparator;
+import org.apache.directory.shared.ldap.cursor.Cursor;
+import org.apache.directory.shared.ldap.cursor.InvalidCursorPositionException;
+import org.junit.Before;
+import org.junit.After;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+
+import jdbm.RecordManager;
+import jdbm.helper.IntegerSerializer;
+import jdbm.recman.BaseRecordManager;
+
+
+/**
+ * Tests the Cursor functionality of a JdbmTable when duplicate keys are 
+ * supported.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class DupsCursorTest
+{
+    private static final Logger LOG = LoggerFactory.getLogger( DupsCursorTest.class.getSimpleName() );
+    private static final String TEST_OUTPUT_PATH = "test.output.path";
+    private static final int SIZE = 15;
+
+    transient Table<Integer,Integer> table;
+    transient File dbFile;
+    transient RecordManager recman;
+
+
+    @Before
+    public void createTable() throws Exception
+    {
+        File tmpDir = null;
+        if ( System.getProperty( TEST_OUTPUT_PATH, null ) != null )
+        {
+            tmpDir = new File( System.getProperty( TEST_OUTPUT_PATH ) );
+        }
+
+        dbFile = File.createTempFile( getClass().getSimpleName(), "db", tmpDir );
+        recman = new BaseRecordManager( dbFile.getAbsolutePath() );
+
+        // gosh this is a terrible use of a global static variable
+        SerializableComparator.setRegistry( new MockComparatorRegistry() );
+
+        table = new JdbmTable<Integer,Integer>( "test", SIZE, recman,
+                new SerializableComparator<Integer>( "" ),
+                new SerializableComparator<Integer>( "" ),
+                null, new IntegerSerializer() );
+        LOG.debug( "Created new table and populated it with data" );
+    }
+
+
+    @After
+    public void destryTable() throws Exception
+    {
+        table.close();
+        table = null;
+        recman.close();
+        recman = null;
+        dbFile.deleteOnExit();
+        // Remove temporary files
+        String fileToDelete = dbFile.getAbsolutePath();
+        new File( fileToDelete ).delete();
+        new File( fileToDelete + ".db" ).delete();
+        new File( fileToDelete + ".lg" ).delete();
+        
+        dbFile = null;
+    }
+
+
+    @Test
+    public void testEmptyTableOperations() throws Exception
+    {
+        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
+        assertFalse( cursor.next() );
+        
+        cursor.afterLast();
+        assertFalse( cursor.previous() );
+
+        cursor.beforeFirst();
+        assertFalse( cursor.next() );
+
+        assertFalse( cursor.first() );
+        assertFalse( cursor.last() );
+    }
+
+
+    @Test
+    public void testNextNoDups() throws Exception
+    {
+        // first try without duplicates at all
+        for ( int ii = 0; ii < SIZE-1; ii++ )
+        {
+            table.put( ii, ii );
+        }
+        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
+
+        int ii = 0;
+        while ( cursor.next() )
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            assertEquals( ii, ( int ) tuple.getKey() );
+            assertEquals( ii, ( int ) tuple.getValue() );
+            ii++;
+        }
+    }
+
+
+    @Test
+    public void testPreviousNoDups() throws Exception
+    {
+        for ( int ii = 0; ii < SIZE-1; ii++ )
+        {
+            table.put( ii, ii );
+        }
+        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
+
+        int ii = SIZE-2;
+        while ( cursor.previous() )
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            assertEquals( ii, ( int ) tuple.getKey() );
+            assertEquals( ii, ( int ) tuple.getValue() );
+            ii--;
+        }
+    }
+
+
+    @Test
+    public void testNextDups() throws Exception
+    {
+        for ( int ii = 0; ii < SIZE*3; ii++ )
+        {
+            if ( ii > 12 && ii < 17 + SIZE )
+            {
+                table.put( 13, ii );
+            }
+            else
+            {
+                table.put( ii, ii );
+            }
+        }
+        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
+
+        int ii = 0;
+        while ( cursor.next() )
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 12 && ii < 17 + SIZE )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+    }
+
+
+    @Test
+    public void testPreviousDups() throws Exception
+    {
+        for ( int ii = 0; ii < SIZE*3; ii++ )
+        {
+            if ( ii > 12 && ii < 17 + SIZE )
+            {
+                table.put( 13, ii );
+            }
+            else
+            {
+                table.put( ii, ii );
+            }
+        }
+        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
+        cursor.afterLast();
+
+        int ii = SIZE*3 - 1;
+        while ( cursor.previous() )
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 12 && ii < 17 + SIZE )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii--;
+        }
+    }
+
+
+    @Test
+    public void testFirstLastUnderDupLimit() throws Exception
+    {
+        for ( int ii = 0; ii < SIZE*2 - 1; ii++ )
+        {
+            if ( ii > 12 && ii < 17 )
+            {
+                table.put( 13, ii );
+            }
+            else
+            {
+                table.put( ii, ii );
+            }
+        }
+        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
+
+        int ii = 0;
+        while ( cursor.next() )
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 12 && ii < 17 )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+
+        cursor.first();
+        ii = 0;
+        do
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 12 && ii < 17 )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+        while ( cursor.next() );
+
+        // now go backwards
+        cursor.afterLast();
+        ii = SIZE*2-2;
+        while ( cursor.previous() )
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 12 && ii < 17 )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii--;
+        }
+
+        // now advance to last and go backwards again
+        cursor.last();
+        ii = SIZE*2-2;
+        do
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 12 && ii < 17 )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii--;
+        }
+        while ( cursor.previous() );
+
+        // advance to first then last and go backwards again
+        cursor.beforeFirst();
+        cursor.afterLast();
+        ii = SIZE*2-2;
+        while ( cursor.previous() )
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 12 && ii < 17 )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii--;
+        }
+    }
+
+
+    @Test
+    public void testFirstLastOverDupLimit() throws Exception
+    {
+        for ( int ii = 0; ii < SIZE*3-1; ii++ )
+        {
+            if ( ii < 2 + SIZE ) // keys with multiple values
+            {
+                table.put( 0, ii );
+            }
+            else // keys with single values
+            {
+                table.put( ii, ii );
+            }
+        }
+        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
+
+        int ii = 0;
+        while ( cursor.next() )
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii < 2 + SIZE )
+            {
+                assertEquals( 0, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+
+        // now go back to first and traverse all over again
+        cursor.first();
+        ii = 0;
+        do
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii < 2 + SIZE )
+            {
+                assertEquals( 0, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+        while ( cursor.next() );
+
+        // now go backwards
+        cursor.afterLast();
+        ii = SIZE*3-2;
+        while ( cursor.previous() )
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+
+            if ( ii < 2 + SIZE )
+            {
+                assertEquals( 0, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii--;
+        }
+
+        // now advance to last and go backwards again
+        cursor.last();
+        ii = SIZE*3-2;
+        do
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii < 2 + SIZE )
+            {
+                assertEquals( 0, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii--;
+        }
+        while ( cursor.previous() );
+
+        // advance to first then last and go backwards again
+        cursor.beforeFirst();
+        cursor.afterLast();
+        ii = SIZE*3-2;
+        while ( cursor.previous() )
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii < 2 + SIZE )
+            {
+                assertEquals( 0, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii--;
+        }
+    }
+
+
+    @Test
+    public void testFirstOverDupLimit() throws Exception
+    {
+        for ( int ii = 0; ii < SIZE*3-1; ii++ )
+        {
+            if ( ii < 2 + SIZE ) // keys with multiple values
+            {
+                table.put( 0, ii );
+            }
+            else // keys with single values
+            {
+                table.put( ii, ii );
+            }
+        }
+        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
+
+        int ii = 0;
+        while ( cursor.next() )
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii < 2 + SIZE )
+            {
+                assertEquals( 0, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+
+        // now go back to first and traverse all over again
+        cursor.first();
+        ii = 0;
+        do
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii < 2 + SIZE )
+            {
+                assertEquals( 0, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+        while ( cursor.next() );
+
+        // now go backwards
+        cursor.afterLast();
+        ii = SIZE*3-2;
+        while ( cursor.previous() )
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+
+            if ( ii < 2 + SIZE )
+            {
+                assertEquals( 0, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii--;
+        }
+
+        // now advance to last and go backwards again
+        cursor.last();
+        ii = SIZE*3-2;
+        do
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii < 2 + SIZE )
+            {
+                assertEquals( 0, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii--;
+        }
+        while ( cursor.previous() );
+
+        // advance to first then last and go backwards again
+        cursor.beforeFirst();
+        cursor.afterLast();
+        ii = SIZE*3-2;
+        while ( cursor.previous() )
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii < 2 + SIZE )
+            {
+                assertEquals( 0, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii--;
+        }
+    }
+
+
+
+
+    @Test
+    public void testLastOverDupLimit() throws Exception
+    {
+        for ( int ii = 0; ii < SIZE*3-1; ii++ )
+        {
+            if ( ii > 2 + SIZE ) // keys with multiple values
+            {
+                table.put( 3 + SIZE, ii );
+            }
+            else // keys with single values
+            {
+                table.put( ii, ii );
+            }
+        }
+        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
+
+        int ii = 0;
+        while ( cursor.next() )
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 2 + SIZE )
+            {
+                assertEquals( 3 + SIZE, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+
+        // now go back to first and traverse all over again
+        cursor.first();
+        ii = 0;
+        do
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 2 + SIZE )
+            {
+                assertEquals( 3 + SIZE, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+        while ( cursor.next() );
+
+        // now go backwards
+        cursor.afterLast();
+        ii = SIZE*3-2;
+        while ( cursor.previous() )
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+
+            if ( ii > 2 + SIZE )
+            {
+                assertEquals( 3 + SIZE, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii--;
+        }
+
+        // now advance to last and go backwards again
+        cursor.last();
+        ii = SIZE*3-2;
+        do
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 2 + SIZE )
+            {
+                assertEquals( 3 + SIZE, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii--;
+        }
+        while ( cursor.previous() );
+
+        // advance to first then last and go backwards again
+        cursor.beforeFirst();
+        cursor.afterLast();
+        ii = SIZE*3-2;
+        while ( cursor.previous() )
+        {
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 2 + SIZE )
+            {
+                assertEquals( 3 + SIZE, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii--;
+        }
+    }
+
+
+    @Test
+    public void testOnEmptyTable() throws Exception
+    {
+        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
+        assertNotNull( cursor );
+        assertFalse( cursor.isClosed() );
+        
+        cursor.before( new Tuple<Integer, Integer>( 1, 2 ) );
+        assertFalse( cursor.available() );
+    }
+
+    
+    @Test
+    public void testOverDupLimit() throws Exception
+    {
+        table.put( 5, 5 );
+        table.put( 6, 6 );
+        for ( int ii = 0; ii < 20; ii++ )
+        {
+            table.put( 7, ii );
+        }
+        table.put( 8, 8 );
+        table.put( 9, 9 );
+        
+        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
+        assertNotNull( cursor );
+        assertFalse( cursor.isClosed() );
+        
+        cursor.before( new Tuple<Integer, Integer>( 7, 2 ) );
+        assertFalse( cursor.available() );
+    }
+
+    
+    @Test
+    public void testUnderDupLimit() throws Exception
+    {
+        table.put( 5, 5 );
+        table.put( 6, 6 );
+        for ( int ii = 0; ii < 10; ii++ )
+        {
+            table.put( 7, ii );
+        }
+        table.put( 8, 8 );
+        table.put( 9, 9 );
+        
+        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
+        assertNotNull( cursor );
+        assertFalse( cursor.isClosed() );
+        
+        cursor.before( new Tuple<Integer, Integer>( 7, 2 ) );
+        assertFalse( cursor.available() );
+    }
+
+
+    @Test
+    public void testBeforeAfterBelowDupLimit() throws Exception
+    {
+        for ( int ii = 0; ii < SIZE*2 - 1; ii++ )
+        {
+            if ( ii > 12 && ii < 17 ) // keys with multiple values
+            {
+                table.put( 13, ii );
+            }
+            else if ( ii > 17 && ii < 21 ) // adds hole with no keys for ii
+            {
+            }
+            else // keys with single values
+            {
+                table.put( ii, ii );
+            }
+        }
+
+        // test before to advance just before a key with a single value
+        int ii = 5;
+        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
+        cursor.before( new Tuple<Integer,Integer>( 5, 5 ) );
+        while ( cursor.next() )
+        {
+            if ( ii > 17 && ii < 21 )
+            {
+                assertFalse( table.has( ii ) );
+                continue;
+            }
+
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 12 && ii < 17 )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+
+        // test before to advance just before a key with a single value but
+        // with a null tuple value which should not advance the dupsCursor
+        ii = 5;
+        cursor = table.cursor();
+        cursor.before( new Tuple<Integer,Integer>( 5, null ) );
+        while ( cursor.next() )
+        {
+            if ( ii > 17 && ii < 21 )
+            {
+                assertFalse( table.has( ii ) );
+                continue;
+            }
+
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 12 && ii < 17 )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+
+        // test before to advance just before a key value pair where the key
+        // does not exist - using value so we hit check for key equality
+        ii = 21;
+        cursor = table.cursor();
+        cursor.before( new Tuple<Integer,Integer>( 18, 18 ) );
+        while ( cursor.next() )
+        {
+            if ( ii > 17 && ii < 21 )
+            {
+                assertFalse( table.has( ii ) );
+                continue;
+            }
+
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 12 && ii < 17 )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+
+        // test after to advance just after the end
+        cursor = table.cursor();
+        cursor.after( new Tuple<Integer,Integer>( 111, null ) );
+        assertFalse( cursor.next() );
+
+        // test after to advance just before a key with a single value
+        ii = 6;
+        cursor = table.cursor();
+        cursor.after( new Tuple<Integer,Integer>( 5, null ) );
+        while ( cursor.next() )
+        {
+            if ( ii > 17 && ii < 21 )
+            {
+                assertFalse( table.has( ii ) );
+                continue;
+            }
+
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 12 && ii < 17 )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+
+        // test before to advance just before a key & value with multiple
+        // values for the key - we should advance just before the value
+        cursor = table.cursor();
+        cursor.before( new Tuple<Integer,Integer>( 13, 14 ) );
+
+        cursor.next();
+        Tuple<Integer,Integer> tuple = cursor.get();
+        assertEquals( 13, ( int ) tuple.getKey() );
+        assertEquals( 14, ( int ) tuple.getValue() );
+        ii = 15;
+
+        while ( cursor.next() )
+        {
+            if ( ii > 17 && ii < 21 )
+            {
+                assertFalse( table.has( ii ) );
+                continue;
+            }
+
+            tuple = cursor.get();
+            if ( ii > 12 && ii < 17 )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+
+        // test after to advance just before a key & value with multiple
+        // values for the key - we should advance just before the value
+        cursor = table.cursor();
+        cursor.after( new Tuple<Integer,Integer>( 13, 14 ) );
+
+        cursor.next();
+        tuple = cursor.get();
+        assertEquals( 13, ( int ) tuple.getKey() );
+        assertEquals( 15, ( int ) tuple.getValue() );
+        ii=16;
+
+        while ( cursor.next() )
+        {
+            if ( ii > 17 && ii < 21 )
+            {
+                assertFalse( table.has( ii ) );
+                continue;
+            }
+
+            tuple = cursor.get();
+            if ( ii > 12 && ii < 17 )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+
+        // test after to advance just before a key that does not exist
+        cursor = table.cursor();
+        cursor.after( new Tuple<Integer,Integer>( 18, null ) );
+
+        cursor.next();
+        tuple = cursor.get();
+        assertEquals( 21, ( int ) tuple.getKey() );
+        assertEquals( 21, ( int ) tuple.getValue() );
+        ii=22;
+
+        while ( cursor.next() )
+        {
+            if ( ii > 17 && ii < 21 )
+            {
+                assertFalse( table.has( ii ) );
+                continue;
+            }
+
+            tuple = cursor.get();
+            if ( ii > 12 && ii < 17 )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+
+        // test after to advance just before a key and value where the key
+        // does not exist - used to force key comparison in after()
+        cursor = table.cursor();
+        cursor.after( new Tuple<Integer,Integer>( 18, 18 ) );
+
+        cursor.next();
+        tuple = cursor.get();
+        assertEquals( 21, ( int ) tuple.getKey() );
+        assertEquals( 21, ( int ) tuple.getValue() );
+        ii=22;
+
+        while ( cursor.next() )
+        {
+            if ( ii > 17 && ii < 21 )
+            {
+                assertFalse( table.has( ii ) );
+                continue;
+            }
+
+            tuple = cursor.get();
+            if ( ii > 12 && ii < 17 )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+    }
+
+
+    @Test
+    public void testBeforeAfterOverDupLimit() throws Exception
+    {
+        for ( int ii = 0; ii < SIZE*3 - 1; ii++ )
+        {
+            if ( ii > 12 && ii < 17 + SIZE ) // keys with multiple values
+            {
+                table.put( 13, ii );
+            }
+            else if ( ii > 17 + SIZE  && ii < 21 + SIZE ) // adds hole with no keys for ii
+            {
+            }
+            else // keys with single values
+            {
+                table.put( ii, ii );
+            }
+        }
+
+        // test before to advance just before a key with a single value
+        int ii = 5;
+        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
+        cursor.before( new Tuple<Integer,Integer>( 5, 5 ) );
+        while ( cursor.next() )
+        {
+            if ( ii > 17 + SIZE && ii < 21 + SIZE )
+            {
+                assertFalse( table.has( ii ) );
+                continue;
+            }
+
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 12 && ii < 17 + SIZE )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+
+        // test before to advance just before a key with a single value but
+        // with a null tuple value which should not advance the dupsCursor
+        ii = 5;
+        cursor = table.cursor();
+        cursor.before( new Tuple<Integer,Integer>( 5, null ) );
+        while ( cursor.next() )
+        {
+            if ( ii > 17 + SIZE && ii < 21 + SIZE )
+            {
+                assertFalse( table.has( ii ) );
+                continue;
+            }
+
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 12 && ii < 17 + SIZE )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+
+        // test before to advance just before a key value pair where the key
+        // does not exist - using value so we hit check for key equality
+        ii = 21 + SIZE;
+        cursor = table.cursor();
+        cursor.before( new Tuple<Integer,Integer>( 18 + SIZE, 18 + SIZE ) );
+        while ( cursor.next() )
+        {
+            if ( ii > 17 + SIZE && ii < 21 + SIZE )
+            {
+                assertFalse( table.has( ii ) );
+                continue;
+            }
+
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 12 && ii < 17 + SIZE )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+
+        // test after to advance just after the end
+        cursor = table.cursor();
+        cursor.after( new Tuple<Integer,Integer>( 111, null ) );
+        assertFalse( cursor.next() );
+
+        // test after to advance just before a key with a single value
+        ii = 6;
+        cursor = table.cursor();
+        cursor.after( new Tuple<Integer,Integer>( 5, null ) );
+        while ( cursor.next() )
+        {
+            if ( ii > 17 + SIZE && ii < 21 + SIZE )
+            {
+                assertFalse( table.has( ii ) );
+                continue;
+            }
+
+            Tuple<Integer,Integer> tuple = cursor.get();
+            if ( ii > 12 && ii < 17 + SIZE )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+
+        // test before to advance just before a key & value with multiple
+        // values for the key - we should advance just before the value
+        cursor = table.cursor();
+        cursor.before( new Tuple<Integer,Integer>( 13, 14 ) );
+
+        cursor.next();
+        Tuple<Integer,Integer> tuple = cursor.get();
+        assertEquals( 13, ( int ) tuple.getKey() );
+        assertEquals( 14, ( int ) tuple.getValue() );
+        ii = 15;
+
+        while ( cursor.next() )
+        {
+            if ( ii > 17 + SIZE && ii < 21 + SIZE )
+            {
+                assertFalse( table.has( ii ) );
+                continue;
+            }
+
+            tuple = cursor.get();
+            if ( ii > 12 && ii < 17 + SIZE )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+
+        // test after to advance just before a key & value with multiple
+        // values for the key - we should advance just before the value
+        cursor = table.cursor();
+        cursor.after( new Tuple<Integer,Integer>( 13, 14 ) );
+
+        cursor.next();
+        tuple = cursor.get();
+        assertEquals( 13, ( int ) tuple.getKey() );
+        assertEquals( 15, ( int ) tuple.getValue() );
+        ii=16;
+
+        while ( cursor.next() )
+        {
+            if ( ii > 17 + SIZE && ii < 21 + SIZE )
+            {
+                assertFalse( table.has( ii ) );
+                continue;
+            }
+
+            tuple = cursor.get();
+            if ( ii > 12 && ii < 17 + SIZE )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+
+        // test after to advance just before a key that does not exist
+        cursor = table.cursor();
+        cursor.after( new Tuple<Integer,Integer>( 18 + SIZE, null ) );
+
+        cursor.next();
+        tuple = cursor.get();
+        assertEquals( 21 + SIZE, ( int ) tuple.getKey() );
+        assertEquals( 21 + SIZE, ( int ) tuple.getValue() );
+        ii=22 + SIZE;
+
+        while ( cursor.next() )
+        {
+            if ( ii > 17 + SIZE && ii < 21 + SIZE )
+            {
+                assertFalse( table.has( ii ) );
+                continue;
+            }
+
+            tuple = cursor.get();
+            if ( ii > 12 && ii < 17 + SIZE )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+
+        // test after to advance just before a key and value where the key
+        // does not exist - used to force key comparison in after()
+        cursor = table.cursor();
+        cursor.after( new Tuple<Integer,Integer>( 18 + SIZE , 18 + SIZE ) );
+
+        cursor.next();
+        tuple = cursor.get();
+        assertEquals( 21 + SIZE, ( int ) tuple.getKey() );
+        assertEquals( 21 + SIZE, ( int ) tuple.getValue() );
+        ii=22+ SIZE;
+
+        while ( cursor.next() )
+        {
+            if ( ii > 17 + SIZE && ii < 21 + SIZE )
+            {
+                assertFalse( table.has( ii ) );
+                continue;
+            }
+
+            tuple = cursor.get();
+            if ( ii > 12 && ii < 17 + SIZE )
+            {
+                assertEquals( 13, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            else
+            {
+                assertEquals( ii, ( int ) tuple.getKey() );
+                assertEquals( ii, ( int ) tuple.getValue() );
+            }
+            ii++;
+        }
+    }
+
+
+    @Test
+    public void testMiscellaneous() throws Exception
+    {
+        Cursor<Tuple<Integer,Integer>> cursor = table.cursor();
+        assertNotNull( cursor );
+        assertTrue( cursor.isElementReused() );
+
+        try
+        {
+            cursor.get();
+            fail( "Should never get here due to invalid cursor position exception." );
+        }
+        catch( InvalidCursorPositionException e )
+        {
+        }
+    }
+}