package org.neo4j.graphalgo.shortestpath; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import org.junit.Test; import org.neo4j.graphdb.Direction; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Path; import org.neo4j.graphdb.RelationshipExpander; import common.Neo4jAlgoTestCase; import common.SimpleGraphBuilder; public class TestShortestPaths extends Neo4jAlgoTestCase { protected PathFinder instantiatePathFinder( int maxDepth, Direction direction ) { return new ShortestPathsFinder( graphDb, maxDepth, RelationshipExpander.forTypes( MyRelTypes.R1, direction ) ); } protected PathFinder instantiatePathFinder( int maxDepth ) { return instantiatePathFinder( maxDepth, Direction.BOTH ); } @Test public void testSimplestGraph() { // Layout: // __ // / \ // (s) (t) // \__/ graph.makeEdge( "s", "t" ); graph.makeEdge( "s", "t" ); PathFinder finder = instantiatePathFinder( 1 ); Collection<Path> paths = finder.findPaths( graph.getNode( "s" ), graph.getNode( "t" ) ); assertEquals( 2, paths.size() ); assertPaths( paths, "s,t", "s,t" ); } @Test public void testAnotherSimpleGraph() { // Layout: // (m) // / \ // (s) (o)---(t) // \ / \ // (n)---(p)---(q) graph.makeEdge( "s", "m" ); graph.makeEdge( "m", "o" ); graph.makeEdge( "s", "n" ); graph.makeEdge( "n", "p" ); graph.makeEdge( "p", "q" ); graph.makeEdge( "q", "t" ); graph.makeEdge( "n", "o" ); graph.makeEdge( "o", "t" ); PathFinder finder = instantiatePathFinder( 6 ); Collection<Path> paths = finder.findPaths( graph.getNode( "s" ), graph.getNode( "t" ) ); assertPaths( paths, "s,m,o,t", "s,n,o,t" ); } @Test public void testCrossedCircle() { // Layout: // (s) // / \ // (3) (1) // | \ / | // | / \ | // (4) (5) // \ / // (t) graph.makeEdge( "s", "1" ); graph.makeEdge( "s", "3" ); graph.makeEdge( "1", "2" ); graph.makeEdge( "1", "4" ); graph.makeEdge( "3", "2" ); graph.makeEdge( "3", "4" ); graph.makeEdge( "2", "t" ); graph.makeEdge( "4", "t" ); PathFinder finder = instantiatePathFinder( 3 ); Collection<Path> paths = finder.findPaths( graph.getNode( "s" ), graph.getNode( "t" ) ); assertPaths( paths, "s,1,2,t", "s,1,4,t", "s,3,2,t", "s,3,4,t" ); ShortestPathsFinder levelFinder = new ShortestPathsFinder( graphDb, 3, RelationshipExpander.forTypes( MyRelTypes.R1, Direction.BOTH ) ); paths = levelFinder.findPaths( graph.getNode( "s" ), graph.getNode( "t" ) ); assertPaths( paths, "s,1,2,t", "s,1,4,t", "s,3,2,t", "s,3,4,t" ); } @Test public void testDirectedFinder() { // Layout: // // (a)->(b)->(c)->(d)->(e)->(f)-------\ // \ v // >(g)->(h)->(i)->(j)->(k)->(l)->(m) // graph.makeEdgeChain( "a,b,c,d,e,f,m" ); graph.makeEdgeChain( "a,g,h,i,j,k,l,m" ); PathFinder finder = instantiatePathFinder( 4, Direction.OUTGOING ); assertPaths( finder.findPaths( graph.getNode( "a" ), graph.getNode( "j" ) ), "a,g,h,i,j" ); } private void assertPaths( Collection<Path> paths, String... pathDefinitions ) { List<String> pathDefs = new ArrayList<String>( Arrays.asList( pathDefinitions ) ); for ( Path path : paths ) { String pathDef = getPathDef( path ); int index = pathDefs.indexOf( pathDef ); if ( index != -1 ) { pathDefs.remove( index ); } else { fail( "Unexpected path " + pathDef ); } } assertTrue( "Should be empty: " + pathDefs.toString(), pathDefs.isEmpty() ); } private String getPathDef( Path path ) { StringBuilder builder = new StringBuilder(); for ( Node node : path.nodes() ) { if ( builder.length() > 0 ) { builder.append( "," ); } builder.append( node.getProperty( SimpleGraphBuilder.KEY_ID ) ); } return builder.toString(); } }