public void Put_edge_between_nodes_in_different_session_should_work() { var graph = new GraphStorage("TestGraph", Env); Node node1, node2, node3; using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { node1 = graph.Commands.CreateNode(tx, JsonFromValue("test1")); node2 = graph.Commands.CreateNode(tx, JsonFromValue("test2")); node3 = graph.Commands.CreateNode(tx, JsonFromValue("test3")); tx.Commit(); } using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { graph.Commands.CreateEdgeBetween(tx, node2, node3); graph.Commands.CreateEdgeBetween(tx, node2, node1); //looping edge also ok! //adding multiple loops will overwrite each other //TODO: add support for multiple edges that have the same keyFrom and keyTo graph.Commands.CreateEdgeBetween(tx, node2, node2); tx.Commit(); } using (var tx = graph.NewTransaction(TransactionFlags.Read)) { var adjacentNodes = graph.Queries.GetAdjacentOf(tx, node2); adjacentNodes.Select(x => x.Key).Should().Contain(new []{ node1.Key, node2.Key, node3.Key}); } }
public async Task BFS_FindOne_with_connected_root_should_return_correct_results() { var graph = new GraphStorage("TestGraph", Env); Node node2; using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { var node1 = graph.Commands.CreateNode(tx, JsonFromValue("test1")); node2 = graph.Commands.CreateNode(tx, JsonFromValue("test2")); var node3 = graph.Commands.CreateNode(tx, JsonFromValue("test3")); graph.Commands.CreateEdgeBetween(tx, node3, node1); graph.Commands.CreateEdgeBetween(tx, node3, node2); graph.Commands.CreateEdgeBetween(tx, node2, node2); graph.Commands.CreateEdgeBetween(tx, node1, node3); tx.Commit(); } using (var tx = graph.NewTransaction(TransactionFlags.Read)) { var bfs = new BreadthFirstSearch(graph, CancelTokenSource.Token); var node = await bfs.FindOne(tx, data => ValueFromJson<string>(data).Equals("test2")); node.Should().NotBeNull(); node.Key.Should().Be(node2.Key); } }
public void Simple_shortest_path_with_constant_edge_weight_should_work() { var graph = new GraphStorage("TestGraph", Env); Node node1, node2, node3; using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { node1 = graph.Commands.CreateNode(tx, JsonFromValue(1)); node2 = graph.Commands.CreateNode(tx, JsonFromValue(2)); node3 = graph.Commands.CreateNode(tx, JsonFromValue(3)); node1.ConnectWith(tx, node2, graph); node1.ConnectWith(tx, node3, graph); node2.ConnectWith(tx, node3, graph); tx.Commit(); } using (var tx = graph.NewTransaction(TransactionFlags.Read)) { var shortestPathsData = GetAlgorithm(tx,graph,node1).Execute(); var shortestNodePath = shortestPathsData.GetShortestPathToNode(node3).ToList(); shortestNodePath.Should().ContainInOrder(node1.Key, node3.Key); } }
public async Task BFS_FindOne_with_disconnected_root_should_return_null() { var graph = new GraphStorage("TestGraph", Env); Node node2; using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { var node1 = graph.Commands.CreateNode(tx, JsonFromValue("test1")); node2 = graph.Commands.CreateNode(tx, JsonFromValue("test2")); var node3 = graph.Commands.CreateNode(tx, JsonFromValue("test3")); graph.Commands.CreateEdgeBetween(tx, node3, node1); graph.Commands.CreateEdgeBetween(tx, node3, node2); //note: root node is selected by using a first node that was added //since Voron.Graph is a directed graph - no node leads from the root node means nothing //can be found tx.Commit(); } using (var tx = graph.NewTransaction(TransactionFlags.Read)) { var bfs = new BreadthFirstSearch(graph, CancelTokenSource.Token); var node = await bfs.FindOne(tx, data => ValueFromJson<string>(data).Equals("test2")); node.Should().BeNull(); } }
public async Task BFS_FindOne_with_only_root_node_in_graph_returns_correct_results() { var graph = new GraphStorage("TestGraph", Env); using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { graph.Commands.CreateNode(tx, JsonFromValue("test1")); tx.Commit(); } using (var tx = graph.NewTransaction(TransactionFlags.Read)) { var bfs = new BreadthFirstSearch(graph, CancelTokenSource.Token); var node = await bfs.FindOne(tx, data => ValueFromJson<string>(data).Equals("test1")); node.Should().NotBeNull(); } }
public void Between_two_equivalent_paths_first_created_should_be_chosen() { var graph = new GraphStorage("TestGraph", Env); Node node1, node2, node3, node4; using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { node1 = graph.Commands.CreateNode(tx, JsonFromValue(1)); node2 = graph.Commands.CreateNode(tx, JsonFromValue(2)); node3 = graph.Commands.CreateNode(tx, JsonFromValue(3)); node4 = graph.Commands.CreateNode(tx, JsonFromValue(4)); node1.ConnectWith(tx, node2, graph, 2); node2.ConnectWith(tx, node4, graph, 1); node1.ConnectWith(tx, node3, graph, 1); node3.ConnectWith(tx, node4, graph, 2); tx.Commit(); } using (var tx = graph.NewTransaction(TransactionFlags.Read)) { var shortestPathsData = GetAlgorithm(tx, graph, node1).Execute(); var shortestNodePath = shortestPathsData.GetShortestPathToNode(node4).ToList(); shortestNodePath.Should().ContainInOrder(node1.Key, node2.Key, node4.Key); } }
public void Simple_shortest_path_with_equal_weights_and_alternative_path2() { var graph = new GraphStorage("TestGraph", Env); Node node1, node2, node3, node4, node5, node6; using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { node1 = graph.Commands.CreateNode(tx, JsonFromValue(1)); node2 = graph.Commands.CreateNode(tx, JsonFromValue(1)); node3 = graph.Commands.CreateNode(tx, JsonFromValue(1)); node4 = graph.Commands.CreateNode(tx, JsonFromValue(1)); node5 = graph.Commands.CreateNode(tx, JsonFromValue(1)); node6 = graph.Commands.CreateNode(tx, JsonFromValue(1)); node1.ConnectWith(tx, node2, graph,1); node1.ConnectWith(tx, node3, graph,15); node3.ConnectWith(tx, node6, graph,1); node2.ConnectWith(tx, node4, graph,1); node4.ConnectWith(tx, node5, graph,1); node5.ConnectWith(tx, node6, graph,1); tx.Commit(); } using (var tx = graph.NewTransaction(TransactionFlags.Read)) { var shortestPathsData = GetAlgorithm(tx, graph, node1).Execute(); var shortestNodePath = shortestPathsData.GetShortestPathToNode(node6).ToList(); shortestNodePath.Should().ContainInOrder(node1.Key,node2.Key, node4.Key, node5.Key); } }
public void No_path_between_nodes_should_result_in_null() { var graph = new GraphStorage("TestGraph", Env); Node node1, node2; using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { node1 = graph.Commands.CreateNode(tx, JsonFromValue(1)); node2 = graph.Commands.CreateNode(tx, JsonFromValue(2)); tx.Commit(); } using (var tx = graph.NewTransaction(TransactionFlags.Read)) { var shortestPathsData = GetAlgorithm(tx, graph, node1).Execute(); var shortestNodePath = shortestPathsData.GetShortestPathToNode(node2); shortestNodePath.Should().BeNull(); } }
public async Task Can_Avoid_Duplicate_Nodes_InParallel_Adds() { var graph = new GraphStorage("TestGraph",Env); Parallel.For(0, 100, i => { using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { graph.Commands.CreateNode(tx, JsonFromValue("newNode" + i)); tx.Commit(); } }); var fetchedKeys = new List<long>(); using (var tx = graph.NewTransaction(TransactionFlags.Read)) { var nodesList = await graph.AdminQueries.GetAllNodes(tx, CancelTokenSource.Token); nodesList.Select(node => node.Key).Should().OnlyHaveUniqueItems(); } }
public void Get_edges_between_existing_and_nonexisting_node_should_return_empty_collection() { var graph = new GraphStorage("TestGraph", Env); long node1Id = 0; using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { var node1 = graph.Commands.CreateNode(tx, JsonFromValue("node1")); Assert.IsNotNull(node1); node1Id = node1.Key; tx.Commit(); } using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { Node node1 = graph.Queries.LoadNode(tx, node1Id); Node node2 = new Node(-2, JsonFromValue("node2")); var edgesList = graph.Queries.GetEdgesBetween(tx, node1, node2); edgesList.Should().BeEmpty(); } }
public void Edge_predicate_should_filter_edge_types_correctly() { var graph = new GraphStorage("TestGraph", Env); Node node1, node2, node3, node4, node5; using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { node1 = graph.Commands.CreateNode(tx, JsonFromValue("test1")); node2 = graph.Commands.CreateNode(tx, JsonFromValue("test2")); node3 = graph.Commands.CreateNode(tx, JsonFromValue("test3")); node4 = graph.Commands.CreateNode(tx, JsonFromValue("test4")); node5 = graph.Commands.CreateNode(tx, JsonFromValue("test5")); tx.Commit(); } using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { graph.Commands.CreateEdgeBetween(tx, node1, node2,type: 1); graph.Commands.CreateEdgeBetween(tx, node1, node3, type: 2); graph.Commands.CreateEdgeBetween(tx, node1, node4, type: 3); graph.Commands.CreateEdgeBetween(tx, node1, node5, type: 2); tx.Commit(); } using (var tx = graph.NewTransaction(TransactionFlags.Read)) { var adjacentNodes = graph.Queries.GetAdjacentOf(tx, node1, type => type == 2); adjacentNodes.Select(x => x.Node.Key).Should().Contain(new[] { node3.Key, node5.Key }); } }
public void Load_nonexisting_node_should_return_null() { var graph = new GraphStorage("TestGraph", Env); using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { var illegalNode = graph.Commands.CreateNode(tx,JsonFromValue("onlyNode")); illegalNode.Should().NotBeNull(); } using (var tx = graph.NewTransaction(TransactionFlags.Read)) { var noneExistingNode = graph.Queries.LoadNode(tx, 1); noneExistingNode.Should().BeNull(); } }
private long Create2DepthHierarchy(GraphStorage graph) { long centerNodeKey = 0; using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { var centerNode = graph.Commands.CreateNode(tx, JsonFromValue("centerNode")); centerNodeKey = centerNode.Key; for (var i = 1; i < 6; i++) { var curChild = graph.Commands.CreateNode(tx,JsonFromValue("childNode" + i.ToString())); graph.Commands.CreateEdgeBetween(tx, centerNode, curChild, JsonFromValue(i.ToString())); for (var j = 1; j < 6; j++) { var curGrandChild = graph.Commands.CreateNode(tx, JsonFromValue(string.Concat("grandchild", i.ToString(), "child", i.ToString()))); graph.Commands.CreateEdgeBetween(tx, curChild, curGrandChild,JsonFromValue((i * 10 + j).ToString())); } } tx.Commit(); } return centerNodeKey; }
public void Can_Iterate_On_Nearest_Nodes() { var graph = new GraphStorage("TestGraph", Env); long centerNodeKey = 0; centerNodeKey = Create2DepthHierarchy(graph); using (var tx = graph.NewTransaction(TransactionFlags.Read)) { var centerNode = graph.Queries.LoadNode(tx, centerNodeKey); var nodeValues = new Dictionary<string, string>(); string curEdgeVal; string curNodeVal; foreach (var curNode in graph.Queries.GetAdjacentOf(tx, centerNode)) { var curEdge = graph.Queries.GetEdgesBetween(tx, centerNode, curNode).FirstOrDefault(); Assert.IsNotNull(curEdge); curEdgeVal = curEdge.Data.Value<string>("Value"); curNodeVal = curNode.Data.Value<string>("Value"); nodeValues.Add(curNodeVal, curEdgeVal); } nodeValues.Values.Should().NotContain("grandchild"); Assert.AreEqual(nodeValues.Count, 5); } }
public async Task BFS_FindMany_with_connected_root_returns_correct_results() { var graph = new GraphStorage("TestGraph", Env); using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { var node1 = graph.Commands.CreateNode(tx, JsonFromValue("test1")); var node2 = graph.Commands.CreateNode(tx, JsonFromValue("test2")); var node3 = graph.Commands.CreateNode(tx, JsonFromValue("test3")); var node4 = graph.Commands.CreateNode(tx, JsonFromValue("test4")); graph.Commands.CreateEdgeBetween(tx, node3, node1); graph.Commands.CreateEdgeBetween(tx, node3, node2); graph.Commands.CreateEdgeBetween(tx, node3, node4); graph.Commands.CreateEdgeBetween(tx, node2, node2); graph.Commands.CreateEdgeBetween(tx, node2, node4); graph.Commands.CreateEdgeBetween(tx, node1, node3); tx.Commit(); } using (var tx = graph.NewTransaction(TransactionFlags.Read)) { var bfs = new BreadthFirstSearch(graph, CancelTokenSource.Token); var nodes = await bfs.FindMany(tx, data => ValueFromJson<string>(data).Contains("2") || ValueFromJson<string>(data).Contains("4")); nodes.Select(x => ValueFromJson<string>(x.Data)).Should().Contain("test2", "test4"); } }
public void Cheap_long_path_over_short_expensive_path_should_be_chosen() { var graph = new GraphStorage("TestGraph", Env); Node node1, node2, node3, node4; using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { node1 = graph.Commands.CreateNode(tx, JsonFromValue(1)); node2 = graph.Commands.CreateNode(tx, JsonFromValue(2)); node3 = graph.Commands.CreateNode(tx, JsonFromValue(3)); node4 = graph.Commands.CreateNode(tx, JsonFromValue(4)); node1.ConnectWith(tx, node2, graph, 1); node2.ConnectWith(tx, node3, graph, 1); node3.ConnectWith(tx, node4, graph, 1); node1.ConnectWith(tx, node4, graph, 10); tx.Commit(); } using (var tx = graph.NewTransaction(TransactionFlags.Read)) { var shortestPathsData = GetAlgorithm(tx, graph, node1).Execute(); var shortestNodePath = shortestPathsData.GetShortestPathToNode(node4); shortestNodePath.Should().ContainInOrder(node1.Key, node2.Key, node3.Key, node4.Key); } }
public void Get_edges_between_two_nonexisting_nodes_should_return_empty_collection() { var graph = new GraphStorage("TestGraph", Env); using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { var node1 = new Node(-1,JsonFromValue("node1")); var node2 = new Node(-2,JsonFromValue("node2")); var edgesList = graph.Queries.GetEdgesBetween(tx, node1, node2); edgesList.Should().BeEmpty(); } }
public void Read_and_writing_system_metadata_should_work() { var graph = new GraphStorage("TestGraph", Env); using (var tx = graph.NewTransaction(TransactionFlags.ReadWrite)) { graph.Commands.PutToSystemMetadata(tx, "Foo", "Bar"); graph.Commands.PutToSystemMetadata(tx, "FooNum", 123); graph.Commands.PutToSystemMetadata(tx, "FooBoolean", false); tx.Commit(); } using (var tx = graph.NewTransaction(TransactionFlags.Read)) { var bar = graph.Queries.GetFromSystemMetadata<string>(tx, "Foo"); var fooNum = graph.Queries.GetFromSystemMetadata<int>(tx, "FooNum"); var fooBoolean = graph.Queries.GetFromSystemMetadata<bool>(tx, "FooBoolean"); Assert.AreEqual("Bar", bar); Assert.AreEqual(123, fooNum); Assert.AreEqual(false, fooBoolean); } }