package com.lordofthejars.nosqlunit.neo4j.integration; import static ch.lambdaj.Lambda.having; import static ch.lambdaj.Lambda.on; import static ch.lambdaj.Lambda.selectFirst; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.collection.IsArrayContainingInAnyOrder.arrayContainingInAnyOrder; import static org.hamcrest.collection.IsArrayWithSize.emptyArray; import static org.junit.Assert.assertThat; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.util.Iterator; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.neo4j.graphdb.DynamicRelationshipType; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Relationship; import org.neo4j.graphdb.Transaction; import org.neo4j.graphdb.factory.GraphDatabaseFactory; import org.neo4j.kernel.GraphDatabaseAPI; import org.neo4j.rest.graphdb.RestGraphDatabase; import org.neo4j.server.WrappingNeoServerBootstrapper; import com.lordofthejars.nosqlunit.core.NoSqlAssertionError; import com.lordofthejars.nosqlunit.neo4j.Neo4jConfiguration; import com.lordofthejars.nosqlunit.neo4j.Neo4jLowLevelOps; import com.lordofthejars.nosqlunit.neo4j.Neo4jOperation; public class WhenNeo4jOperationsAreRequired { private static final String DB_PATH = "target/neo4j-test"; private static final String WELL_FORMED_GRAPH = "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\"\n" + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + " xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns\n" + " http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n" + " <key id=\"weight\" for=\"edge\" attr.name=\"weight\" attr.type=\"float\"/>\n" + " <key id=\"name\" for=\"node\" attr.name=\"name\" attr.type=\"string\"/>\n" + " <key id=\"age\" for=\"node\" attr.name=\"age\" attr.type=\"int\"/>\n" + " <key id=\"lang\" for=\"node\" attr.name=\"lang\" attr.type=\"string\"/>\n" + " <graph id=\"G\" edgedefault=\"directed\">\n" + " <node id=\"15\">\n" + " <data key=\"name\">I</data>\n" + " </node>\n" + " <node id=\"25\">\n" + " <data key=\"name\">you</data>\n" + " </node>\n" + " <node id=\"3\">\n" + " <data key=\"name\">him</data>\n" + " </node>\n" + " <edge id=\"1\" source=\"15\" target=\"25\" label=\"know\">\n" + " <data key=\"weight\">0.5</data>\n" + " </edge>\n" + " <edge id=\"2\" source=\"15\" target=\"3\" label=\"know\">\n" + " <data key=\"weight\">0.8</data>\n" + " </edge>\n" + " </graph>\n" + "</graphml>"; private static final String WELL_FORMED_GRAPH_WITH_MANUAL_INDEX = "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\"\n" + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + " xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns\n" + " http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd\">\n" + " <key id=\"weight\" for=\"edge\" attr.name=\"weight\" attr.type=\"float\"/>\n" + " <key id=\"name\" for=\"node\" attr.name=\"name\" attr.type=\"string\"/>\n" + " <key id=\"age\" for=\"node\" attr.name=\"age\" attr.type=\"int\"/>\n" + " <key id=\"lang\" for=\"node\" attr.name=\"lang\" attr.type=\"string\"/>\n" + " <graph id=\"G\" edgedefault=\"directed\">\n" + " <node id=\"15\">\n" + " <data key=\"name\">I</data>\n" + " <index name=\"myindex\" key=\"mykey\">myvalue</index>"+ " </node>\n" + " <node id=\"25\">\n" + " <data key=\"name\">you</data>\n" + " </node>\n" + " <node id=\"3\">\n" + " <data key=\"name\">him</data>\n" + " </node>\n" + " <edge id=\"1\" source=\"15\" target=\"25\" label=\"know\">\n" + " <data key=\"weight\">0.5</data>\n" + " </edge>\n" + " <edge id=\"2\" source=\"15\" target=\"3\" label=\"know\">\n" + " <data key=\"weight\">0.8</data>\n" + " </edge>\n" + " </graph>\n" + "</graphml>"; private static final String EXPECTED_GRAPH = "<?xml version=\"1.0\" ?>\n" + "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.1/graphml.xsd\">\n" + "<key id=\"name\" for=\"edge\" attr.name=\"name\" attr.type=\"string\"></key>\n" + "<key id=\"message\" for=\"node\" attr.name=\"message\" attr.type=\"string\"></key>\n" + " <graph id=\"G\" edgedefault=\"directed\">\n" + " <node id=\"0\"></node>\n" + " <node id=\"1\">\n" + " <data key=\"message\">Hello</data>\n" + " </node>\n" + " <node id=\"2\">\n" + " <data key=\"message\">World!</data>\n" + " </node>\n" + " <edge id=\"0\" source=\"1\" target=\"2\" label=\"KNOWS\">\n" + " <data key=\"name\">Alex</data>\n" + " </edge>\n" + " </graph>\n" + "</graphml>"; private static final String EXPECTED_GRAPH_WITHOUT_REFERENCE = "<?xml version=\"1.0\" ?>\n" + "<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.1/graphml.xsd\">\n" + "<key id=\"name\" for=\"edge\" attr.name=\"name\" attr.type=\"string\"></key>\n" + "<key id=\"message\" for=\"node\" attr.name=\"message\" attr.type=\"string\"></key>\n" + " <graph id=\"G\" edgedefault=\"directed\">\n" + " <node id=\"1\">\n" + " <data key=\"message\">Hello</data>\n" + " </node>\n" + " <node id=\"2\">\n" + " <data key=\"message\">World!</data>\n" + " </node>\n" + " <edge id=\"0\" source=\"1\" target=\"2\" label=\"KNOWS\">\n" + " <data key=\"name\">Alex</data>\n" + " </edge>\n" + " </graph>\n" + "</graphml>"; private GraphDatabaseService newEmbeddedDatabase; private Transaction tx; @Before public void setUp() { clearDb(); newEmbeddedDatabase = new GraphDatabaseFactory().newEmbeddedDatabase(DB_PATH); } @After public void tearDown() throws Exception { if (newEmbeddedDatabase!=null) newEmbeddedDatabase.shutdown(); } @Test public void insert_opertation_should_add_data_and_indexes_into_graph() { Neo4jConfiguration neo4jConfiguration = new Neo4jConfiguration(); neo4jConfiguration.setGraphDatabaseService(newEmbeddedDatabase); Neo4jOperation neo4jOperation = new Neo4jOperation(newEmbeddedDatabase); neo4jOperation.insert(new ByteArrayInputStream(WELL_FORMED_GRAPH_WITH_MANUAL_INDEX.getBytes())); Iterable<Node> allNodes = neo4jOperation.getAllNodes(); Iterable<Relationship> allRelationships = neo4jOperation.getAllRelationships(); Node firstNode = selectFirst(allNodes, having(on(Node.class).getProperty("name"), equalTo("I"))); assertThat(firstNode, notNullValue()); Node secondNode = selectFirst(allNodes, having(on(Node.class).getProperty("name"), equalTo("you"))); assertThat(secondNode, notNullValue()); Node thirdNode = selectFirst(allNodes, having(on(Node.class).getProperty("name"), equalTo("him"))); assertThat(thirdNode, notNullValue()); Relationship firstRelationship = selectFirst(allRelationships, having(on(Relationship.class).getProperty("weight"), equalTo(Float.parseFloat("0.5")))); assertThat(firstRelationship, notNullValue()); Relationship secondRelationship = selectFirst(allRelationships, having(on(Relationship.class).getProperty("weight"), equalTo(Float.parseFloat("0.8")))); assertThat(secondRelationship, notNullValue()); String[] nodeIndexNames = newEmbeddedDatabase.index().nodeIndexNames(); assertThat(nodeIndexNames, arrayContainingInAnyOrder("myindex")); neo4jOperation.deleteAll(); } @Test public void delete_opertation_should_remove_indexes_of_graph() { Neo4jConfiguration neo4jConfiguration = new Neo4jConfiguration(); neo4jConfiguration.setGraphDatabaseService(newEmbeddedDatabase); Neo4jOperation neo4jOperation = new Neo4jOperation(newEmbeddedDatabase); neo4jOperation.insert(new ByteArrayInputStream(WELL_FORMED_GRAPH_WITH_MANUAL_INDEX.getBytes())); neo4jOperation.deleteAll(); String[] nodeIndexNames = neo4jOperation.nodeIndexNames(); assertThat(nodeIndexNames, emptyArray()); } @Test public void insert_opertation_should_add_data_into_graph() { Neo4jConfiguration neo4jConfiguration = new Neo4jConfiguration(); neo4jConfiguration.setGraphDatabaseService(newEmbeddedDatabase); Neo4jOperation neo4jOperation = new Neo4jOperation(newEmbeddedDatabase); neo4jOperation.insert(new ByteArrayInputStream(WELL_FORMED_GRAPH.getBytes())); Iterable<Node> allNodes = neo4jOperation.getAllNodes(); Iterable<Relationship> allRelationships = neo4jOperation.getAllRelationships(); Node firstNode = selectFirst(allNodes, having(on(Node.class).getProperty("name"), equalTo("I"))); assertThat(firstNode, notNullValue()); Node secondNode = selectFirst(allNodes, having(on(Node.class).getProperty("name"), equalTo("you"))); assertThat(secondNode, notNullValue()); Node thirdNode = selectFirst(allNodes, having(on(Node.class).getProperty("name"), equalTo("him"))); assertThat(thirdNode, notNullValue()); Relationship firstRelationship = selectFirst(allRelationships, having(on(Relationship.class).getProperty("weight"), equalTo(Float.parseFloat("0.5")))); assertThat(firstRelationship, notNullValue()); Relationship secondRelationship = selectFirst(allRelationships, having(on(Relationship.class).getProperty("weight"), equalTo(Float.parseFloat("0.8")))); assertThat(secondRelationship, notNullValue()); } @Test public void delete_all_operation_should_remove_all_data_from_graph_except_reference_node() { Neo4jConfiguration neo4jConfiguration = new Neo4jConfiguration(); neo4jConfiguration.setGraphDatabaseService(newEmbeddedDatabase); Neo4jOperation neo4jOperation = new Neo4jOperation(newEmbeddedDatabase); createNodes(newEmbeddedDatabase); neo4jOperation.deleteAll(); Iterator<Node> allNodes = neo4jOperation.getAllNodes().iterator(); Iterator<Relationship> allRelationships = neo4jOperation.getAllRelationships().iterator(); assertThat(allNodes.hasNext(), is(false)); assertThat(allRelationships.hasNext(), is(false)); } @Test public void insert_opertation_should_add_indexes_into_remote_graph() { WrappingNeoServerBootstrapper graphDb = new WrappingNeoServerBootstrapper((GraphDatabaseAPI) newEmbeddedDatabase); graphDb.start(); RestGraphDatabase graphDatabaseService = new RestGraphDatabase("http://localhost:7474/db/data"); Neo4jConfiguration neo4jConfiguration = new Neo4jConfiguration(); neo4jConfiguration.setGraphDatabaseService(graphDatabaseService); Neo4jOperation neo4jOperation = new Neo4jOperation(graphDatabaseService); neo4jOperation.insert(new ByteArrayInputStream(WELL_FORMED_GRAPH_WITH_MANUAL_INDEX.getBytes())); String[] nodeIndexNames = graphDatabaseService.index().nodeIndexNames(); assertThat(nodeIndexNames, arrayContainingInAnyOrder("myindex")); neo4jOperation.deleteAll(); } @Test public void delete_all_operation_should_remove_all_data_from_graph_except_reference_node_in_remote_mode() { WrappingNeoServerBootstrapper graphDb = new WrappingNeoServerBootstrapper((GraphDatabaseAPI) newEmbeddedDatabase); graphDb.start(); RestGraphDatabase graphDatabaseService = new RestGraphDatabase("http://localhost:7474/db/data"); Neo4jConfiguration neo4jConfiguration = new Neo4jConfiguration(); neo4jConfiguration.setGraphDatabaseService(graphDatabaseService); Neo4jOperation neo4jOperation = new Neo4jOperation(graphDatabaseService); createNodes(graphDatabaseService); neo4jOperation.deleteAll(); Iterator<Node> allNodes = Neo4jLowLevelOps.getAllNodes(graphDatabaseService); Iterator<Relationship> allRelationships = Neo4jLowLevelOps.getAllRelationships(graphDatabaseService); assertThat(allNodes.hasNext(), is(false)); assertThat(allRelationships.hasNext(), is(false)); graphDb.stop(); } @Test public void should_assert_same_expected_data_and_inserted_data() { Neo4jConfiguration neo4jConfiguration = new Neo4jConfiguration(); neo4jConfiguration.setGraphDatabaseService(newEmbeddedDatabase); Neo4jOperation neo4jOperation = new Neo4jOperation(newEmbeddedDatabase); createNodes(newEmbeddedDatabase); boolean expectedDataEqualsToInserted = neo4jOperation.databaseIs(new ByteArrayInputStream(EXPECTED_GRAPH.getBytes())); assertThat(expectedDataEqualsToInserted, is(true)); } @Test(expected=NoSqlAssertionError.class) public void should_throw_exception_same_expected_data_and_inserted_data() { Neo4jConfiguration neo4jConfiguration = new Neo4jConfiguration(); neo4jConfiguration.setGraphDatabaseService(newEmbeddedDatabase); Neo4jOperation neo4jOperation = new Neo4jOperation(newEmbeddedDatabase); createNodes(newEmbeddedDatabase); neo4jOperation.databaseIs(new ByteArrayInputStream(EXPECTED_GRAPH_WITHOUT_REFERENCE.getBytes())); } private void createNodes(GraphDatabaseService newEmbeddedDatabase) { Transaction tx = newEmbeddedDatabase.beginTx(); try { Node firstNode = newEmbeddedDatabase.createNode(); firstNode.setProperty("message", "Hello"); Node secondNode = newEmbeddedDatabase.createNode(); secondNode.setProperty("message", "World!"); Relationship relationship = firstNode.createRelationshipTo( secondNode, DynamicRelationshipType.withName("KNOWS")); relationship.setProperty("name", "Alex"); tx.success(); } finally { tx.finish(); } } private void clearDb() { try { org.apache.commons.io.FileUtils.deleteDirectory(new File(DB_PATH)); } catch (IOException e) { throw new RuntimeException(e); } } }