/*
* Copyright (c) 2002-2009 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.index.impl.btree;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.neo4j.graphdb.Node;
import org.neo4j.index.Neo4jTestCase;
public class TestBTree extends Neo4jTestCase
{
private BTree bTree;
@Before
public void setUpBTree() throws Exception
{
Node bNode = graphDb().createNode();
graphDb().getReferenceNode().createRelationshipTo( bNode,
BTree.RelTypes.TREE_ROOT );
bTree = new BTree( graphDb(), bNode );
}
@After
public void tearDownBTree() throws Exception
{
bTree.delete();
}
@Test
public void testBasicBTree()
{
bTree.addEntry( 'c', 'c' );
bTree.addEntry( 'n', 'n' );
bTree.addEntry( 'g', 'g' );
bTree.addEntry( 'a', 'a' );
bTree.addEntry( 'h', 'h' );
bTree.addEntry( 'e', 'e' );
bTree.addEntry( 'k', 'k' );
bTree.addEntry( 'q', 'q' );
bTree.addEntry( 'm', 'm' );
bTree.addEntry( 'f', 'f' );
bTree.addEntry( 'w', 'w' );
bTree.addEntry( 'l', 'l' );
bTree.addEntry( 't', 't' );
bTree.addEntry( 'z', 'z' );
bTree.addEntry( 'd', 'd' );
bTree.addEntry( 'p', 'p' );
bTree.addEntry( 'r', 'r' );
bTree.addEntry( 'x', 'x' );
bTree.addEntry( 'y', 'y' );
bTree.addEntry( 's', 's' );
bTree.validateTree();
assertEquals( bTree.removeEntry( 'h' ), 'h' );
assertEquals( bTree.removeEntry( 't' ), 't' );
assertEquals( bTree.removeEntry( 'r' ), 'r' );
bTree.validateTree();
assertEquals( bTree.removeEntry( 'e' ), 'e' );
assertEquals( bTree.removeEntry( 'a' ), 'a' );
assertEquals( bTree.removeEntry( 'x' ), 'x' );
assertEquals( bTree.removeEntry( 'y' ), 'y' );
assertEquals( bTree.removeEntry( 'z' ), 'z' );
assertEquals( bTree.removeEntry( 'w' ), 'w' );
bTree.validateTree();
assertEquals( bTree.removeEntry( 's' ), 's' );
assertEquals( bTree.removeEntry( 'q' ), 'q' );
assertEquals( bTree.removeEntry( 'm' ), 'm' );
assertEquals( bTree.removeEntry( 'n' ), 'n' );
assertEquals( bTree.removeEntry( 'p' ), 'p' );
assertEquals( bTree.removeEntry( 'k' ), 'k' );
bTree.validateTree();
assertEquals( bTree.removeEntry( 'l' ), 'l' );
assertEquals( bTree.removeEntry( 'g' ), 'g' );
assertEquals( bTree.removeEntry( 'c' ), 'c' );
assertEquals( bTree.removeEntry( 'd' ), 'd' );
assertEquals( bTree.removeEntry( 'f' ), 'f' );
bTree.validateTree();
}
private long getNextUniqueLong( Set<Long> usedValues, java.util.Random r )
{
long value = r.nextLong();
while ( usedValues.contains( value ) )
{
value = r.nextInt();
}
usedValues.add( value );
return value;
}
@Test
public void testSomeMore()
{
java.util.Random r = new java.util.Random( System.currentTimeMillis() );
long[] values = new long[500];
Set<Long> valueSet = new HashSet<Long>();
for ( int i = 0; i < values.length; i++ )
{
values[i] = getNextUniqueLong( valueSet, r );
}
for ( int i = 0; i < values.length; i++ )
{
assertTrue( bTree.getEntry( values[i] ) == null );
bTree.addEntry( values[i], values[i] );
}
bTree.validateTree();
for ( int i = values.length -1; i > -1; i-- )
{
assertEquals( bTree.getEntry( values[i] ), values[i] );
}
Collections.shuffle( Arrays.asList( values ) );
for ( int i = 0; i < values.length; i++ )
{
assertEquals( bTree.removeEntry( values[i] ), values[i] );
assertTrue( bTree.getEntry( values[i] ) == null );
if ( i % 100 == 0 )
{
bTree.validateTree();
}
}
}
@Test
public void testGetValues()
{
bTree.addEntry( 'c', 'c' );
bTree.addEntry( 'n', 'n' );
bTree.addEntry( 'g', 'g' );
bTree.addEntry( 'a', 'a' );
bTree.addEntry( 'h', 'h' );
bTree.addEntry( 'e', 'e' );
for ( Object value : bTree.values() )
{
assertTrue( value instanceof Character );
}
}
@Test
public void testClosestEntry()
{
for ( long i = 1; i < 256; i+=2 )
{
bTree.addEntry( i, i );
}
for ( long i = 0; i < 255; i+=2 )
{
assertEquals( i + 1, bTree.getClosestHigherEntry( i ) );
}
for ( long i = 2; i < 257; i+=2 )
{
assertEquals( i - 1, bTree.getClosestLowerEntry( i ) );
}
}
}