/*
* 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.kernel.impl.core;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import org.junit.Test;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.Transaction;
import org.neo4j.kernel.Config;
import org.neo4j.kernel.EmbeddedGraphDatabase;
import org.neo4j.kernel.impl.AbstractNeo4jTestCase;
import org.neo4j.kernel.impl.MyRelTypes;
import org.neo4j.kernel.impl.core.GraphDbModule;
import org.neo4j.kernel.impl.core.NodeManager;
import org.neo4j.kernel.impl.transaction.XaDataSourceManager;
import org.neo4j.kernel.impl.transaction.xaframework.XaDataSource;
public class TestNeo4j extends AbstractNeo4jTestCase
{
@Test
public void testReferenceNode()
{
// fix this test when we can set reference node again
Node oldReferenceNode = null;
try
{
// get old reference node if one is set
oldReferenceNode = getGraphDb().getReferenceNode();
}
catch ( RuntimeException e )
{
// ok no one set, oldReferenceNode is null then
}
try
{
GraphDbModule graphDbModule = ((EmbeddedGraphDatabase) getGraphDb()).getConfig()
.getGraphDbModule();
Node newReferenceNode = getGraphDb().createNode();
graphDbModule.setReferenceNodeId( (int) newReferenceNode.getId() );
assertEquals( newReferenceNode, getGraphDb().getReferenceNode() );
newReferenceNode.delete();
if ( oldReferenceNode != null )
{
graphDbModule.setReferenceNodeId( (int) oldReferenceNode.getId() );
assertEquals( oldReferenceNode, getGraphDb().getReferenceNode() );
}
}
catch ( Exception e )
{
e.printStackTrace();
fail( "" + e );
}
}
@Test
public void testBasicNodeRelationships()
{
Node firstNode = null;
Node secondNode = null;
Relationship rel = null;
// Create nodes and a relationship between them
firstNode = getGraphDb().createNode();
assertNotNull( "Failure creating first node", firstNode );
secondNode = getGraphDb().createNode();
assertNotNull( "Failure creating second node", secondNode );
rel = firstNode.createRelationshipTo( secondNode, MyRelTypes.TEST );
assertNotNull( "Relationship is null", rel );
RelationshipType relType = rel.getType();
assertNotNull( "Relationship's type is is null", relType );
// Verify that the node reports that it has a relationship of
// the type we created above
assertTrue( firstNode.getRelationships( relType ).iterator().hasNext() );
assertTrue( secondNode.getRelationships( relType ).iterator().hasNext() );
Iterable<Relationship> allRels = null;
// Verify that both nodes return the relationship we created above
allRels = firstNode.getRelationships();
assertTrue( this.objectExistsInIterable( rel, allRels ) );
allRels = firstNode.getRelationships( relType );
assertTrue( this.objectExistsInIterable( rel, allRels ) );
allRels = secondNode.getRelationships();
assertTrue( this.objectExistsInIterable( rel, allRels ) );
allRels = secondNode.getRelationships( relType );
assertTrue( this.objectExistsInIterable( rel, allRels ) );
// Verify that the relationship reports that it is associated with
// firstNode and secondNode
Node[] relNodes = rel.getNodes();
assertEquals( "A relationship should always be connected to exactly "
+ "two nodes", relNodes.length, 2 );
assertTrue( "Relationship says that it isn't connected to firstNode",
this.objectExistsInArray( firstNode, relNodes ) );
assertTrue( "Relationship says that it isn't connected to secondNode",
this.objectExistsInArray( secondNode, relNodes ) );
assertTrue( "The other node should be secondNode but it isn't", rel
.getOtherNode( firstNode ).equals( secondNode ) );
assertTrue( "The other node should be firstNode but it isn't", rel
.getOtherNode( secondNode ).equals( firstNode ) );
rel.delete();
secondNode.delete();
firstNode.delete();
}
private boolean objectExistsInIterable( Relationship rel,
Iterable<Relationship> allRels )
{
for ( Relationship iteratedRel : allRels )
{
if ( rel.equals( iteratedRel ) )
{
return true;
}
}
return false;
}
private boolean objectExistsInArray( Object obj, Object[] objArray )
{
for ( int i = 0; i < objArray.length; i++ )
{
if ( objArray[i].equals( obj ) )
{
return true;
}
}
return false;
}
// private static enum RelTypes implements RelationshipType
// {
// ONE_MORE_RELATIONSHIP;
// }
// TODO: fix this testcase
@Test
public void testIdUsageInfo()
{
GraphDbModule graphDbModule = ((EmbeddedGraphDatabase) getGraphDb()).getConfig()
.getGraphDbModule();
NodeManager nm = graphDbModule.getNodeManager();
long nodeCount = nm.getNumberOfIdsInUse( Node.class );
long relCount = nm.getNumberOfIdsInUse( Relationship.class );
if ( nodeCount > nm.getHighestPossibleIdInUse( Node.class ) )
{
// fail( "Node count greater than highest id " + nodeCount );
}
if ( relCount > nm.getHighestPossibleIdInUse( Relationship.class ) )
{
// fail( "Rel count greater than highest id " + relCount );
}
// assertTrue( nodeCount <= nm.getHighestPossibleIdInUse( Node.class )
// );
// assertTrue( relCount <= nm.getHighestPossibleIdInUse(
// Relationship.class ) );
Node n1 = nm.createNode();
Node n2 = nm.createNode();
Relationship r1 = n1.createRelationshipTo( n2, MyRelTypes.TEST );
// assertEquals( nodeCount + 2, nm.getNumberOfIdsInUse( Node.class ) );
// assertEquals( relCount + 1, nm.getNumberOfIdsInUse(
// Relationship.class ) );
r1.delete();
n1.delete();
n2.delete();
// must commit for ids to be reused
try
{
getTransaction().success();
getTransaction().finish();
}
catch ( Exception e )
{
fail( "" + e );
}
// assertEquals( nodeCount, nm.getNumberOfIdsInUse( Node.class ) );
// assertEquals( relCount, nm.getNumberOfIdsInUse( Relationship.class )
// );
setTransaction( getGraphDb().beginTx() );
}
@Test
public void testRandomPropertyName()
{
Node node1 = getGraphDb().createNode();
String key = "random_"
+ new Random( System.currentTimeMillis() ).nextLong();
node1.setProperty( key, "value" );
assertEquals( "value", node1.getProperty( key ) );
node1.delete();
}
@Test
public void testNodeChangePropertyArray() throws Exception
{
Transaction tx = getTransaction();
tx.finish();
tx = getGraphDb().beginTx();
Node node;
try
{
node = getGraphDb().createNode();
tx.success();
}
finally
{
tx.finish();
}
tx = getGraphDb().beginTx();
try
{
node.setProperty( "test", new String[] { "value1" } );
tx.success();
}
finally
{
tx.finish();
}
tx = getGraphDb().beginTx();
try
{
node.setProperty( "test", new String[] { "value1", "value2" } );
// no success, we wanna test rollback on this operation
}
finally
{
tx.finish();
}
tx = getGraphDb().beginTx();
try
{
String[] value = (String[]) node.getProperty( "test" );
assertEquals( 1, value.length );
assertEquals( "value1", value[0] );
tx.success();
}
finally
{
tx.finish();
}
setTransaction( getGraphDb().beginTx() );
}
@Test
public void testMultipleNeos()
{
GraphDatabaseService graphDb2 = new EmbeddedGraphDatabase( getStorePath( "test-neo2" ) );
Transaction tx2 = graphDb2.beginTx();
getGraphDb().createNode();
graphDb2.createNode();
tx2.success();
tx2.finish();
graphDb2.shutdown();
}
@Test
public void testGetAllNode()
{
long highId = getNodeManager().getHighestPossibleIdInUse( Node.class );
if ( highId >= 0 && highId < 10000 )
{
int count = 0;
for ( Node node : getEmbeddedGraphDb().getAllNodes() )
{
count++;
}
boolean found = false;
Node newNode = getGraphDb().createNode();
newTransaction();
int oldCount = count;
count = 0;
for ( Node node : getEmbeddedGraphDb().getAllNodes() )
{
count++;
if ( node.equals( newNode ) )
{
found = true;
}
}
assertTrue( found );
assertEquals( count, oldCount + 1 );
// Tests a bug in the "all nodes" iterator
Iterator<Node> allNodesIterator =
getEmbeddedGraphDb().getAllNodes().iterator();
assertNotNull( allNodesIterator.next() );
newNode.delete();
newTransaction();
found = false;
count = 0;
for ( Node node : getEmbeddedGraphDb().getAllNodes() )
{
count++;
if ( node.equals( newNode ) )
{
found = true;
}
}
assertTrue( !found );
assertEquals( count, oldCount );
}
// else we skip test, takes too long
}
@Test
public void testMultipleShutdown()
{
getGraphDb().shutdown();
getGraphDb().shutdown();
}
@Test
public void testKeepLogsConfig()
{
Map<String,String> config = new HashMap<String,String>();
config.put( Config.KEEP_LOGICAL_LOGS, "nioneodb" );
EmbeddedGraphDatabase db = new EmbeddedGraphDatabase(
"target/configdb", config );
XaDataSourceManager xaDsMgr =
db.getConfig().getTxModule().getXaDataSourceManager();
XaDataSource xaDs = xaDsMgr.getXaDataSource( "nioneodb" );
assertTrue( xaDs.isLogicalLogKept() );
db.shutdown();
config.remove( Config.KEEP_LOGICAL_LOGS );
db = new EmbeddedGraphDatabase( "target/configdb", config );
xaDsMgr = db.getConfig().getTxModule().getXaDataSourceManager();
xaDs = xaDsMgr.getXaDataSource( "nioneodb" );
assertTrue( !xaDs.isLogicalLogKept() );
db.shutdown();
config.put( Config.KEEP_LOGICAL_LOGS, "true" );
db = new EmbeddedGraphDatabase( "target/configdb", config );
xaDsMgr = db.getConfig().getTxModule().getXaDataSourceManager();
xaDs = xaDsMgr.getXaDataSource( "nioneodb" );
assertTrue( xaDs.isLogicalLogKept() );
}
}