Skip to content

Commit

Permalink
Some (passing) test cases for record based cursors
Browse files Browse the repository at this point in the history
  • Loading branch information
thobe authored and fickludd committed Nov 9, 2017
1 parent 5325e7d commit e84fcb1
Show file tree
Hide file tree
Showing 39 changed files with 2,966 additions and 317 deletions.
21 changes: 14 additions & 7 deletions community/kernel-api/pom.xml
Expand Up @@ -65,6 +65,20 @@ the relevant Commercial Agreement.
</dependency>

<!-- Test dependencies -->
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-values</artifactId>
<version>${project.version}</version>
<scope>test</scope>
<type>test-jar</type>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-graphdb-api</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
Expand All @@ -80,13 +94,6 @@ the relevant Commercial Agreement.
<artifactId>hamcrest-library</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-values</artifactId>
<version>${project.version}</version>
<scope>test</scope>
<type>test-jar</type>
</dependency>
</dependencies>

</project>
Expand Up @@ -20,24 +20,15 @@
package org.neo4j.internal.kernel.api;

/**
* Entry point for the Cypher Kernel API
* Entry point for the Kernel API
*
* Usage is roughly
*
* try ( PlannerFrame plannerFrame = kernelAPI.beginPlannerFrame() )
* {
* LogicalPlan logicalPlan = Planner.plan( queryText, plannerFrame );
* PhysicalPlan physicalPlan = PhysicalPlanner.specialize( logicalPlan, plannerFrame );
* ExecutableQuery executableQuery = ExecutableMapping.map( physicalPlan, token );
*
* try ( Runtime runtime = logicalPlan.beginRuntime() )
* {
* executableQuery.execute( runtime );
* }
* }
* Usage pattern is under development
*/
public interface KernelAPI
{
PlannerFrame beginPlannerFrame();
Transaction beginTransaction();

CursorFactory cursors();

Token token();
}
Expand Up @@ -73,7 +73,7 @@ public interface Read
* @param nodeReference
* a reference from {@link NodeCursor#nodeReference()}.
* @param reference
* a reference from {@link NodeCursor#relationshipGroupReference()}.
* a reference from {@link NodeCursor#relationshipReference()}.
* @param cursor
* the cursor to use for consuming the results.
*/
Expand Down
Expand Up @@ -27,6 +27,7 @@
* Write provides all write operations
* Schema provides all schema operations, meaning index and constraint creation and deletion
*/
@Deprecated
public interface Runtime extends AutoCloseable
{
CursorFactory cursorFactory();
Expand Down
Expand Up @@ -19,7 +19,8 @@
*/
package org.neo4j.internal.kernel.api;

public interface Transaction extends Read, Write
public interface Transaction extends Read, Write, AutoCloseable
{

void success();
void failure();
}
Expand Up @@ -24,7 +24,7 @@
/**
* Defines the write operations of the Kernel API.
*/
interface Write
public interface Write
{
long nodeCreate();

Expand Down
@@ -0,0 +1,141 @@
/*
* Copyright (c) 2002-2017 "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.internal.kernel.api;

import org.junit.Test;

import org.neo4j.collection.primitive.Primitive;
import org.neo4j.collection.primitive.PrimitiveLongSet;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.RelationshipType;
import org.neo4j.graphdb.Transaction;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.neo4j.graphdb.RelationshipType.withName;

public abstract class DeepRelationshipTraversalCursorTestBase<G extends KernelAPIReadTestSupport>
extends KernelAPIReadTestBase<G>
{
private static long three_root;
private static int expected_total, expected_unique;

private RelationshipType PARENT = withName( "PARENT" );

@Override
void createTestGraph( GraphDatabaseService graphDb )
{
try ( Transaction tx = graphDb.beginTx() )
{
Node root = graphDb.createNode();
three_root = root.getId();

Node[] leafs = new Node[32];
for ( int i = 0; i < leafs.length; i++ )
{
leafs[i] = graphDb.createNode();
}
int offset = 0, duplicate = 12;

Node interdup = graphDb.createNode();
interdup.createRelationshipTo( root, PARENT );
offset = relate( duplicate, leafs, offset, interdup );
for ( int i = 0; i < 5; i++ )
{
Node inter = graphDb.createNode();
inter.createRelationshipTo( root, PARENT );
offset = relate( 3 + i, leafs, offset, inter );
}
interdup.createRelationshipTo( root, PARENT );
for ( int i = 0; i < 4; i++ )
{
Node inter = graphDb.createNode();
inter.createRelationshipTo( root, PARENT );
offset = relate( 2 + i, leafs, offset, inter );
}

Node inter = graphDb.createNode();
inter.createRelationshipTo( root, PARENT );
offset = relate( 1, leafs, offset, inter );

expected_total = offset + duplicate;
expected_unique = leafs.length;

tx.success();
}
}

private int relate( int count, Node[] selection, int offset, Node parent )
{
for ( int i = 0; i < count; i++ )
{
selection[offset++ % selection.length].createRelationshipTo( parent, PARENT );
}
return offset;
}

@Test
public void shouldTraverseTreeOfDepthThree() throws Exception
{
try ( NodeCursor node = cursors.allocateNodeCursor();
RelationshipGroupCursor group = cursors.allocateRelationshipGroupCursor();
RelationshipTraversalCursor relationship1 = cursors.allocateRelationshipTraversalCursor();
RelationshipTraversalCursor relationship2 = cursors.allocateRelationshipTraversalCursor();
PrimitiveLongSet leafs = Primitive.longSet() )
{
long total = 0;

// when
read.singleNode( three_root, node );
assertTrue( "access root node", node.next() );
node.relationships( group );
assertFalse( "single root", node.next() );

assertTrue( "access group of root", group.next() );
group.incoming( relationship1 );
assertFalse( "single group of root", group.next() );

while ( relationship1.next() )
{
relationship1.neighbour( node );

assertTrue( "child level 1", node.next() );
node.relationships( group );
assertFalse( "single node", node.next() );

assertTrue( "group of level 1 child", group.next() );
group.incoming( relationship2 );
assertFalse( "single group of level 1 child", group.next() );

while ( relationship2.next() )
{
leafs.add( relationship2.neighbourNodeReference() );
total++;
}
}

// then
assertEquals( "total number of leaf nodes", expected_total, total );
assertEquals( "number of distinct leaf nodes", expected_unique, leafs.size() );
}
}
}
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2002-2017 "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 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.internal.kernel.api;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.rules.TemporaryFolder;

import java.io.IOException;

import org.neo4j.graphdb.GraphDatabaseService;

@SuppressWarnings( "WeakerAccess" )
public abstract class KernelAPIReadTestBase<G extends KernelAPIReadTestSupport>
{
protected static final TemporaryFolder folder = new TemporaryFolder();
protected static KernelAPIReadTestSupport testSupport;
protected static KernelAPI kernel;
protected CursorFactory cursors;
protected Transaction read;

/**
* Creates a new instance of KernelAPITestSupport, which will be used to execute the concrete test
*/
public abstract G newTestSupport();

/**
* Create the graph which all test in the class will be executed against. The graph is only built once,
* regardless of the number of tests.
*
* @param graphDb a graph API which should be used to build the test graph
*/
abstract void createTestGraph( GraphDatabaseService graphDb );

@Before
public void setupGraph() throws IOException
{
if ( testSupport == null )
{
folder.create();
testSupport = newTestSupport();
testSupport.setup( folder.getRoot(), this::createTestGraph );
kernel = testSupport.kernelToTest();
}
testSupport.beforeEachTest();
cursors = kernel.cursors();
read = kernel.beginTransaction();
}

@After
public void closeTransaction() throws Exception
{
read.success();
read.close();
}

@AfterClass
public static void tearDown() throws Exception
{
if ( testSupport != null )
{
testSupport.tearDown();
folder.delete();
testSupport = null;
kernel = null;
}
}
}
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2002-2017 "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 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.internal.kernel.api;

import java.io.File;
import java.io.IOException;
import java.util.function.Consumer;

import org.neo4j.graphdb.GraphDatabaseService;

public interface KernelAPIReadTestSupport
{
void setup( File storeDir, Consumer<GraphDatabaseService> create ) throws IOException;

void beforeEachTest();

KernelAPI kernelToTest();

void tearDown();
}

0 comments on commit e84fcb1

Please sign in to comment.