Example #1
0
        public void ShouldSendCommandAndNotCareAboutResultsAsync()
        {
            // Arrange
            const string queryText = @"return 1";
            var parameters = new Dictionary<string, object>();

            var cypherQuery = new CypherQuery(queryText, parameters, CypherResultMode.Set);
            var cypherApiQuery = new CypherApiQuery(cypherQuery);

            using (var testHarness = new RestTestHarness
            {
                {
                    MockRequest.PostObjectAsJson("/cypher", cypherApiQuery),
                    MockResponse.Http((int)HttpStatusCode.OK)
                }
            })
            {
                var graphClient = testHarness.CreateAndConnectGraphClient();

                bool raisedEvent = false;

                graphClient.OperationCompleted += (sender, e) => { raisedEvent = true; };

                //Act
                var task = graphClient.ExecuteCypherAsync(cypherQuery);
                task.Wait();

                Assert.IsTrue(raisedEvent, "Raised OperationCompleted");
            }
        }
Example #2
0
        public void ShouldSendCommandAndNotCareAboutResults()
        {
            // Arrange
            const string queryText = @"START d=node({p0}), e=node({p1}) CREATE UNIQUE d-[:foo]->e";
            var parameters = new Dictionary<string, object>
            {
                {"p0", 215},
                {"p1", 219}
            };

            var cypherQuery = new CypherQuery(queryText, parameters, CypherResultMode.Set);
            var cypherApiQuery = new CypherApiQuery(cypherQuery);

            using (var testHarness = new RestTestHarness
            {
                {
                    MockRequest.PostObjectAsJson("/cypher", cypherApiQuery),
                    MockResponse.Http((int)HttpStatusCode.OK)
                }
            })
            {
                var graphClient = testHarness.CreateAndConnectGraphClient();

                //Act
                graphClient.ExecuteCypher(cypherQuery);
            }
        }
Example #3
0
        public void GraphClientFactoryUseCase()
        {
            const string queryText = @"MATCH (d) RETURN d";

            var cypherQuery = new CypherQuery(queryText, null, CypherResultMode.Set, CypherResultFormat.Rest);
            var cypherApiQuery = new CypherApiQuery(cypherQuery);

            using (var testHarness = new RestTestHarness
            {
                { MockRequest.Get("/"), MockResponse.NeoRoot() },
                { MockRequest.PostObjectAsJson("/cypher", cypherApiQuery), new MockResponse { StatusCode = HttpStatusCode.OK } }
            })
            {
                var httpClient = testHarness.GenerateHttpClient(testHarness.BaseUri);

                var executeConfiguration = new ExecutionConfiguration
                {
                    HttpClient = httpClient,
                    UserAgent =
                        string.Format("Neo4jClient/{0}", typeof(NeoServerConfiguration).Assembly.GetName().Version),
                    UseJsonStreaming = true,
                    JsonConverters = GraphClient.DefaultJsonConverters
                };

                var configuration = NeoServerConfiguration.GetConfiguration(new Uri(testHarness.BaseUri), null, null, executeConfiguration);

                var factory = new GraphClientFactory(configuration);

                using (var client = factory.Create(httpClient))
                {
                    client.Cypher.Match("(d)").Return<object>("d").ExecuteWithoutResults();
                }
            }
        }
Example #4
0
        public void WhenAsyncCommandFails_ShouldNotRaiseCompleted()
        {
            // Arrange
            const string queryText = @"return 1";
            var parameters = new Dictionary<string, object>();

            var cypherQuery = new CypherQuery(queryText, parameters, CypherResultMode.Set);
            var cypherApiQuery = new CypherApiQuery(cypherQuery);

            using (var testHarness = new RestTestHarness
            {
                {
                    MockRequest.PostObjectAsJson("/cypher", cypherApiQuery),
                    MockResponse.Throws()
                }
            })
            {
                var graphClient = testHarness.CreateAndConnectGraphClient();

                bool raisedEvent = false;

                graphClient.OperationCompleted += (sender, e) => { raisedEvent = true; };

                //Act
                var task = graphClient.ExecuteCypherAsync(cypherQuery)
                    .ContinueWith(t =>
                    {
                        Assert.IsTrue(t.IsFaulted);
                        Assert.IsInstanceOf<MockResponseThrowsException>(t.Exception.Flatten().InnerException);
                    });
                task.Wait();

                Assert.IsFalse(raisedEvent, "Raised OperationCompleted");
            }
        }
        [Test] public void ShouldDeserializePathsResultAsSetBased()
        {
            // Arrange
            const string queryText = @"START d=node({p0}), e=node({p1})
                                        MATCH p = allShortestPaths( d-[*..15]-e )
                                        RETURN p";

            var parameters = new Dictionary<string, object>
                {
                    {"p0", 215},
                    {"p1", 219}
                };

            var cypherQuery = new CypherQuery(queryText, parameters, CypherResultMode.Set, CypherResultFormat.Rest);
            var cypherApiQuery = new CypherApiQuery(cypherQuery);

            using (var testHarness = new RestTestHarness
                {
                    {
                    MockRequest.PostObjectAsJson("/cypher", cypherApiQuery),
                    MockResponse.Json(HttpStatusCode.OK,
                    @"{
                              'data' : [ [ {
                                'start' : 'http://foo/db/data/node/215',
                                'nodes' : [ 'http://foo/db/data/node/215', 'http://foo/db/data/node/0', 'http://foo/db/data/node/219' ],
                                'length' : 2,
                                'relationships' : [ 'http://foo/db/data/relationship/247', 'http://foo/db/data/relationship/257' ],
                                'end' : 'http://foo/db/data/node/219'
                              } ], [ {
                                'start' : 'http://foo/db/data/node/215',
                                'nodes' : [ 'http://foo/db/data/node/215', 'http://foo/db/data/node/1', 'http://foo/db/data/node/219' ],
                                'length' : 2,
                                'relationships' : [ 'http://foo/db/data/relationship/248', 'http://foo/db/data/relationship/258' ],
                                'end' : 'http://foo/db/data/node/219'
                              } ] ],
                              'columns' : [ 'p' ]
                            }")
                    }
                })
            {
                var graphClient = testHarness.CreateAndConnectGraphClient();

                //Act
                var results = graphClient
                    .ExecuteGetCypherResults<PathsResult>(cypherQuery)
                    .ToArray();

                //Assert
                Assert.IsInstanceOf<IEnumerable<PathsResult>>(results);
                Assert.AreEqual(results.First().Length, 2);
                Assert.AreEqual(results.First().Start, "http://foo/db/data/node/215");
                Assert.AreEqual(results.First().End, "http://foo/db/data/node/219");
                Assert.AreEqual(results.Skip(1).First().Length, 2);
                Assert.AreEqual(results.Skip(1).First().Start, "http://foo/db/data/node/215");
                Assert.AreEqual(results.Skip(1).First().End, "http://foo/db/data/node/219");
            }
        }
        public void SendingNullParametersShouldNotRaiseExceptionWhenExecutingCypher()
        {
            const string queryText = @"MATCH (d) RETURN d";
            
            var cypherQuery = new CypherQuery(queryText, null, CypherResultMode.Set, CypherResultFormat.Rest);
            var cypherApiQuery = new CypherApiQuery(cypherQuery);

            using (var testHarness = new RestTestHarness
            {
                {
                    MockRequest.PostObjectAsJson("/cypher", cypherApiQuery),
                    MockResponse.Http((int)HttpStatusCode.OK)
                }
            })
            {
                var graphClient = testHarness.CreateAndConnectGraphClient();

                // execute cypher with "null" parameters
                graphClient.ExecuteCypher(cypherQuery);
            }
        }
        public void ShouldSupportAnonymousReturnTypesEndToEnd()
        {
            const string queryText = "START root=node({p0})\r\nMATCH root-->other\r\nRETURN other AS Foo";
            var parameters = new Dictionary<string, object>
            {
                {"p0", 123}
            };

            var cypherQuery = new CypherQuery(queryText, parameters, CypherResultMode.Projection);
            var cypherApiQuery = new CypherApiQuery(cypherQuery);

            using (var testHarness = new RestTestHarness
            {
                {
                    MockRequest.PostObjectAsJson("/cypher", cypherApiQuery),
                    MockResponse.Json(HttpStatusCode.OK, @"{
              'columns' : [ 'Foo' ],
              'data' : [ [ {
            'outgoing_relationships' : 'http://localhost:8000/db/data/node/748/relationships/out',
            'data' : {
              'Name' : 'Antimony',
              'UniqueId' : 38
            },
            'all_typed_relationships' : 'http://localhost:8000/db/data/node/748/relationships/all/{-list|&|types}',
            'traverse' : 'http://localhost:8000/db/data/node/748/traverse/{returnType}',
            'self' : 'http://localhost:8000/db/data/node/748',
            'property' : 'http://localhost:8000/db/data/node/748/properties/{key}',
            'outgoing_typed_relationships' : 'http://localhost:8000/db/data/node/748/relationships/out/{-list|&|types}',
            'properties' : 'http://localhost:8000/db/data/node/748/properties',
            'incoming_relationships' : 'http://localhost:8000/db/data/node/748/relationships/in',
            'extensions' : {
            },
            'create_relationship' : 'http://localhost:8000/db/data/node/748/relationships',
            'paged_traverse' : 'http://localhost:8000/db/data/node/748/paged/traverse/{returnType}{?pageSize,leaseTime}',
            'all_relationships' : 'http://localhost:8000/db/data/node/748/relationships/all',
            'incoming_typed_relationships' : 'http://localhost:8000/db/data/node/748/relationships/in/{-list|&|types}'
              } ], [ {
            'outgoing_relationships' : 'http://localhost:8000/db/data/node/610/relationships/out',
            'data' : {
              'Name' : 'Bauxite',
              'UniqueId' : 24
            },
            'all_typed_relationships' : 'http://localhost:8000/db/data/node/610/relationships/all/{-list|&|types}',
            'traverse' : 'http://localhost:8000/db/data/node/610/traverse/{returnType}',
            'self' : 'http://localhost:8000/db/data/node/610',
            'property' : 'http://localhost:8000/db/data/node/610/properties/{key}',
            'outgoing_typed_relationships' : 'http://localhost:8000/db/data/node/610/relationships/out/{-list|&|types}',
            'properties' : 'http://localhost:8000/db/data/node/610/properties',
            'incoming_relationships' : 'http://localhost:8000/db/data/node/610/relationships/in',
            'extensions' : {
            },
            'create_relationship' : 'http://localhost:8000/db/data/node/610/relationships',
            'paged_traverse' : 'http://localhost:8000/db/data/node/610/paged/traverse/{returnType}{?pageSize,leaseTime}',
            'all_relationships' : 'http://localhost:8000/db/data/node/610/relationships/all',
            'incoming_typed_relationships' : 'http://localhost:8000/db/data/node/610/relationships/in/{-list|&|types}'
              } ], [ {
            'outgoing_relationships' : 'http://localhost:8000/db/data/node/749/relationships/out',
            'data' : {
              'Name' : 'Bismuth',
              'UniqueId' : 37
            },
            'all_typed_relationships' : 'http://localhost:8000/db/data/node/749/relationships/all/{-list|&|types}',
            'traverse' : 'http://localhost:8000/db/data/node/749/traverse/{returnType}',
            'self' : 'http://localhost:8000/db/data/node/749',
            'property' : 'http://localhost:8000/db/data/node/749/properties/{key}',
            'outgoing_typed_relationships' : 'http://localhost:8000/db/data/node/749/relationships/out/{-list|&|types}',
            'properties' : 'http://localhost:8000/db/data/node/749/properties',
            'incoming_relationships' : 'http://localhost:8000/db/data/node/749/relationships/in',
            'extensions' : {
            },
            'create_relationship' : 'http://localhost:8000/db/data/node/749/relationships',
            'paged_traverse' : 'http://localhost:8000/db/data/node/749/paged/traverse/{returnType}{?pageSize,leaseTime}',
            'all_relationships' : 'http://localhost:8000/db/data/node/749/relationships/all',
            'incoming_typed_relationships' : 'http://localhost:8000/db/data/node/749/relationships/in/{-list|&|types}'
              } ] ]
            }")
                }
            })
            {
                var graphClient = testHarness.CreateAndConnectGraphClient();

                var results = graphClient
                    .Cypher
                    .Start("root", graphClient.RootNode)
                    .Match("root-->other")
                    .Return(other => new
                    {
                        Foo = other.As<Commodity>()
                    })
                    .Results
                    .ToList();

                Assert.AreEqual(3, results.Count());

                var result = results[0];
                Assert.AreEqual("Antimony", result.Foo.Name);
                Assert.AreEqual(38, result.Foo.UniqueId);

                result = results[1];
                Assert.AreEqual("Bauxite", result.Foo.Name);
                Assert.AreEqual(24, result.Foo.UniqueId);

                result = results[2];
                Assert.AreEqual("Bismuth", result.Foo.Name);
                Assert.AreEqual(37, result.Foo.UniqueId);
            }
        }
        public void WhenExecuteCypherFails_ShouldRaiseCompletedWithException()
        {
            // Arrange
            const string queryText = @"bad cypher";
            var parameters = new Dictionary<string, object>();

            var cypherQuery = new CypherQuery(queryText, parameters, CypherResultMode.Set);
            var cypherApiQuery = new CypherApiQuery(cypherQuery);

            using (var testHarness = new RestTestHarness
            {
                {
                    MockRequest.PostObjectAsJson("/cypher", cypherApiQuery),
                    MockResponse.Throws()
                }
            })
            {
                var graphClient = testHarness.CreateAndConnectGraphClient();

                OperationCompletedEventArgs eventArgs = null;

                graphClient.OperationCompleted += (sender, e) => { eventArgs = e; };

                //Act
                Assert.Throws<MockResponseThrowsException>(() =>
                {
                    graphClient.ExecuteCypher(cypherQuery);
                }, "We should expect an exception");

                Assert.IsNotNull(eventArgs, "but we should also have received the completion event");
                Assert.IsTrue(eventArgs.HasException);
                Assert.AreEqual(typeof(MockResponseThrowsException), eventArgs.Exception.GetType());
                Assert.AreEqual(-1, eventArgs.ResourcesReturned);
            }
        }
        public void ShouldDeserializeSimpleTableStructure()
        {
            // Arrange
            const string queryText = @"
                START x = node({p0})
                MATCH x-[r]->n
                RETURN type(r) AS RelationshipType, n.Name? AS Name, n.UniqueId? AS UniqueId
                LIMIT 3";
            var cypherQuery = new CypherQuery(
                queryText,
                new Dictionary<string, object>
                {
                    {"p0", 123}
                },
                CypherResultMode.Projection,
                CypherResultFormat.Rest);

            var cypherApiQuery = new CypherApiQuery(cypherQuery);

            using(var testHarness = new RestTestHarness
                {
                    {
                        MockRequest.PostObjectAsJson("/cypher", cypherApiQuery),
                        MockResponse.Json(HttpStatusCode.OK, @"{
                                'data' : [ [ 'HOSTS', 'foo', 44321 ], [ 'LIKES', 'bar', 44311 ], [ 'HOSTS', 'baz', 42586 ] ],
                                'columns' : [ 'RelationshipType', 'Name', 'UniqueId' ]
                            }")
                    }
                })
            {
                var graphClient = testHarness.CreateAndConnectGraphClient();

                //Act
                var results = graphClient.ExecuteGetCypherResults<SimpleResultDto>(cypherQuery);

                //Assert
                Assert.IsInstanceOf<IEnumerable<SimpleResultDto>>(results);

                var resultsArray = results.ToArray();
                Assert.AreEqual(3, resultsArray.Count());

                var firstResult = resultsArray[0];
                Assert.AreEqual("HOSTS", firstResult.RelationshipType);
                Assert.AreEqual("foo", firstResult.Name);
                Assert.AreEqual(44321, firstResult.UniqueId);

                var secondResult = resultsArray[1];
                Assert.AreEqual("LIKES", secondResult.RelationshipType);
                Assert.AreEqual("bar", secondResult.Name);
                Assert.AreEqual(44311, secondResult.UniqueId);

                var thirdResult = resultsArray[2];
                Assert.AreEqual("HOSTS", thirdResult.RelationshipType);
                Assert.AreEqual("baz", thirdResult.Name);
                Assert.AreEqual(42586, thirdResult.UniqueId);
            }
        }
        public void ShouldPromoteBadQueryResponseToNiceException()
        {
            // Arrange
            const string queryText = @"broken query";
            var cypherQuery = new CypherQuery(queryText, new Dictionary<string, object>(), CypherResultMode.Projection, CypherResultFormat.Rest);
            var cypherApiQuery = new CypherApiQuery(cypherQuery);

            using (var testHarness = new RestTestHarness
                {
                    {
                        MockRequest.PostObjectAsJson("/cypher", cypherApiQuery),
                        MockResponse.Json(HttpStatusCode.BadRequest, @"{
  'message' : 'expected START or CREATE\n\'bad query\'\n ^',
  'exception' : 'SyntaxException',
  'fullname' : 'org.neo4j.cypher.SyntaxException',
  'stacktrace' : [ 'org.neo4j.cypher.internal.parser.v1_9.CypherParserImpl.parse(CypherParserImpl.scala:45)', 'org.neo4j.cypher.CypherParser.parse(CypherParser.scala:44)', 'org.neo4j.cypher.ExecutionEngine$$anonfun$prepare$1.apply(ExecutionEngine.scala:80)', 'org.neo4j.cypher.ExecutionEngine$$anonfun$prepare$1.apply(ExecutionEngine.scala:80)', 'org.neo4j.cypher.internal.LRUCache.getOrElseUpdate(LRUCache.scala:37)', 'org.neo4j.cypher.ExecutionEngine.prepare(ExecutionEngine.scala:80)', 'org.neo4j.cypher.ExecutionEngine.execute(ExecutionEngine.scala:72)', 'org.neo4j.cypher.ExecutionEngine.execute(ExecutionEngine.scala:76)', 'org.neo4j.cypher.javacompat.ExecutionEngine.execute(ExecutionEngine.java:79)', 'org.neo4j.server.rest.web.CypherService.cypher(CypherService.java:94)', 'java.lang.reflect.Method.invoke(Unknown Source)', 'org.neo4j.server.rest.security.SecurityFilter.doFilter(SecurityFilter.java:112)' ]
}")
                    }
                })
            {
                var graphClient = testHarness.CreateAndConnectGraphClient();

                var ex = Assert.Throws<NeoException>(() => graphClient.ExecuteGetCypherResults<ResultWithRelationshipDto>(cypherQuery));
                Assert.AreEqual("SyntaxException: expected START or CREATE\n'bad query'\n ^", ex.Message);
                Assert.AreEqual("expected START or CREATE\n'bad query'\n ^", ex.NeoMessage);
                Assert.AreEqual("SyntaxException", ex.NeoExceptionName);
                Assert.AreEqual("org.neo4j.cypher.SyntaxException", ex.NeoFullName);

                var expectedStack = new[]
                {
                    "org.neo4j.cypher.internal.parser.v1_9.CypherParserImpl.parse(CypherParserImpl.scala:45)",
                    "org.neo4j.cypher.CypherParser.parse(CypherParser.scala:44)",
                    "org.neo4j.cypher.ExecutionEngine$$anonfun$prepare$1.apply(ExecutionEngine.scala:80)",
                    "org.neo4j.cypher.ExecutionEngine$$anonfun$prepare$1.apply(ExecutionEngine.scala:80)",
                    "org.neo4j.cypher.internal.LRUCache.getOrElseUpdate(LRUCache.scala:37)",
                    "org.neo4j.cypher.ExecutionEngine.prepare(ExecutionEngine.scala:80)",
                    "org.neo4j.cypher.ExecutionEngine.execute(ExecutionEngine.scala:72)",
                    "org.neo4j.cypher.ExecutionEngine.execute(ExecutionEngine.scala:76)",
                    "org.neo4j.cypher.javacompat.ExecutionEngine.execute(ExecutionEngine.java:79)",
                    "org.neo4j.server.rest.web.CypherService.cypher(CypherService.java:94)",
                    "java.lang.reflect.Method.invoke(Unknown Source)",
                    "org.neo4j.server.rest.security.SecurityFilter.doFilter(SecurityFilter.java:112)"
                };
                CollectionAssert.AreEqual(expectedStack, ex.NeoStackTrace);
            }
        }
        public void DoesntSendMaxExecutionTime_WhenNotAddedToQuery()
        {
            const string queryText = @"START d=node({p0}), e=node({p1})
                                        MATCH p = allShortestPaths( d-[*..15]-e )
                                        RETURN p";

            var parameters = new Dictionary<string, object>
                {
                    {"p0", 215},
                    {"p1", 219}
                };

            var cypherQuery = new CypherQuery(queryText, parameters, CypherResultMode.Set);
            var cypherApiQuery = new CypherApiQuery(cypherQuery);

            using (var testHarness = new RestTestHarness
            {
                {
                    MockRequest.Get(""),
                    MockResponse.NeoRoot()
                },
                {
                    MockRequest.PostObjectAsJson("/cypher", cypherApiQuery),
                    MockResponse.Json(HttpStatusCode.OK,
                    @"{
                              'data' : [ [ {
                                'start' : 'http://foo/db/data/node/215',
                                'nodes' : [ 'http://foo/db/data/node/215', 'http://foo/db/data/node/0', 'http://foo/db/data/node/219' ],
                                'length' : 2,
                                'relationships' : [ 'http://foo/db/data/relationship/247', 'http://foo/db/data/relationship/257' ],
                                'end' : 'http://foo/db/data/node/219'
                              } ], [ {
                                'start' : 'http://foo/db/data/node/215',
                                'nodes' : [ 'http://foo/db/data/node/215', 'http://foo/db/data/node/1', 'http://foo/db/data/node/219' ],
                                'length' : 2,
                                'relationships' : [ 'http://foo/db/data/relationship/248', 'http://foo/db/data/relationship/258' ],
                                'end' : 'http://foo/db/data/node/219'
                              } ] ],
                              'columns' : [ 'p' ]
                            }")
                }
            })
            {
                var httpClient = testHarness.GenerateHttpClient(testHarness.BaseUri);
                var graphClient = new GraphClient(new Uri(testHarness.BaseUri), httpClient);
                graphClient.Connect();

                httpClient.ClearReceivedCalls();
                ((IRawGraphClient)graphClient).ExecuteGetCypherResults<object>(cypherQuery);

                var call = httpClient.ReceivedCalls().Single();
                var requestMessage = (HttpRequestMessage)call.GetArguments()[0];
                Assert.IsFalse(requestMessage.Headers.Any(h => h.Key == "max-execution-time"));
            }
        }
        public void ShouldDeserializeTableStructureWithNodeDataObjects()
        {
            // Arrange
            const string queryText = @"
                START x = node({p0})
                MATCH x-[r]->n
                RETURN x AS Fooness, type(r) AS RelationshipType, n.Name? AS Name, n.UniqueId? AS UniqueId
                LIMIT 3";
            var cypherQuery = new CypherQuery(
                queryText,
                new Dictionary<string, object>
                    {
                        {"p0", 123}
                    },
                CypherResultMode.Projection,
                CypherResultFormat.Rest);

            var cypherApiQuery = new CypherApiQuery(cypherQuery);

            using (var testHarness = new RestTestHarness
                {
                    {
                        MockRequest.PostObjectAsJson("/cypher", cypherApiQuery),
                        MockResponse.Json(HttpStatusCode.OK, @"{
                                'data' : [ [ {
                                'outgoing_relationships' : 'http://foo/db/data/node/0/relationships/out',
                                'data' : {
                                    'Bar' : 'bar',
                                    'Baz' : 'baz'
                                },
                                'traverse' : 'http://foo/db/data/node/0/traverse/{returnType}',
                                'all_typed_relationships' : 'http://foo/db/data/node/0/relationships/all/{-list|&|types}',
                                'property' : 'http://foo/db/data/node/0/properties/{key}',
                                'self' : 'http://foo/db/data/node/0',
                                'properties' : 'http://foo/db/data/node/0/properties',
                                'outgoing_typed_relationships' : 'http://foo/db/data/node/0/relationships/out/{-list|&|types}',
                                'incoming_relationships' : 'http://foo/db/data/node/0/relationships/in',
                                'extensions' : {
                                },
                                'create_relationship' : 'http://foo/db/data/node/0/relationships',
                                'paged_traverse' : 'http://foo/db/data/node/0/paged/traverse/{returnType}{?pageSize,leaseTime}',
                                'all_relationships' : 'http://foo/db/data/node/0/relationships/all',
                                'incoming_typed_relationships' : 'http://foo/db/data/node/0/relationships/in/{-list|&|types}'
                                }, 'HOSTS', 'foo', 44321 ], [ {
                                'outgoing_relationships' : 'http://foo/db/data/node/0/relationships/out',
                                'data' : {
                                    'Bar' : 'bar',
                                    'Baz' : 'baz'
                                },
                                'traverse' : 'http://foo/db/data/node/0/traverse/{returnType}',
                                'all_typed_relationships' : 'http://foo/db/data/node/0/relationships/all/{-list|&|types}',
                                'property' : 'http://foo/db/data/node/0/properties/{key}',
                                'self' : 'http://foo/db/data/node/2',
                                'properties' : 'http://foo/db/data/node/0/properties',
                                'outgoing_typed_relationships' : 'http://foo/db/data/node/0/relationships/out/{-list|&|types}',
                                'incoming_relationships' : 'http://foo/db/data/node/0/relationships/in',
                                'extensions' : {
                                },
                                'create_relationship' : 'http://foo/db/data/node/0/relationships',
                                'paged_traverse' : 'http://foo/db/data/node/0/paged/traverse/{returnType}{?pageSize,leaseTime}',
                                'all_relationships' : 'http://foo/db/data/node/0/relationships/all',
                                'incoming_typed_relationships' : 'http://foo/db/data/node/0/relationships/in/{-list|&|types}'
                                }, 'LIKES', 'bar', 44311 ], [ {
                                'outgoing_relationships' : 'http://foo/db/data/node/0/relationships/out',
                                'data' : {
                                    'Bar' : 'bar',
                                    'Baz' : 'baz'
                                },
                                'traverse' : 'http://foo/db/data/node/0/traverse/{returnType}',
                                'all_typed_relationships' : 'http://foo/db/data/node/0/relationships/all/{-list|&|types}',
                                'property' : 'http://foo/db/data/node/0/properties/{key}',
                                'self' : 'http://foo/db/data/node/12',
                                'properties' : 'http://foo/db/data/node/0/properties',
                                'outgoing_typed_relationships' : 'http://foo/db/data/node/0/relationships/out/{-list|&|types}',
                                'incoming_relationships' : 'http://foo/db/data/node/0/relationships/in',
                                'extensions' : {
                                },
                                'create_relationship' : 'http://foo/db/data/node/0/relationships',
                                'paged_traverse' : 'http://foo/db/data/node/0/paged/traverse/{returnType}{?pageSize,leaseTime}',
                                'all_relationships' : 'http://foo/db/data/node/0/relationships/all',
                                'incoming_typed_relationships' : 'http://foo/db/data/node/0/relationships/in/{-list|&|types}'
                                }, 'HOSTS', 'baz', 42586 ] ],
                                'columns' : [ 'Fooness', 'RelationshipType', 'Name', 'UniqueId' ]
                            }")
                    }
                })
            {
                var graphClient = testHarness.CreateAndConnectGraphClient();

                //Act
                var results = graphClient.ExecuteGetCypherResults<ResultWithNodeDataObjectsDto>(cypherQuery);

                //Assert
                Assert.IsInstanceOf<IEnumerable<ResultWithNodeDataObjectsDto>>(results);

                var resultsArray = results.ToArray();
                Assert.AreEqual(3, resultsArray.Count());

                var firstResult = resultsArray[0];
                Assert.AreEqual("bar", firstResult.Fooness.Bar);
                Assert.AreEqual("baz", firstResult.Fooness.Baz);
                Assert.AreEqual("HOSTS", firstResult.RelationshipType);
                Assert.AreEqual("foo", firstResult.Name);
                Assert.AreEqual(44321, firstResult.UniqueId);

                var secondResult = resultsArray[1];
                Assert.AreEqual("bar", secondResult.Fooness.Bar);
                Assert.AreEqual("baz", secondResult.Fooness.Baz);
                Assert.AreEqual("LIKES", secondResult.RelationshipType);
                Assert.AreEqual("bar", secondResult.Name);
                Assert.AreEqual(44311, secondResult.UniqueId);

                var thirdResult = resultsArray[2];
                Assert.AreEqual("bar", thirdResult.Fooness.Bar);
                Assert.AreEqual("baz", thirdResult.Fooness.Baz);
                Assert.AreEqual("HOSTS", thirdResult.RelationshipType);
                Assert.AreEqual("baz", thirdResult.Name);
                Assert.AreEqual(42586, thirdResult.UniqueId);
            }
        }
        public void ShouldDeserializeArrayOfNodesInPropertyAsResultOfCollectFunctionInCypherQuery()
        {
            // Arrange
            var cypherQuery = new CypherQuery(
                @"START root=node(0) MATCH root-[:HAS_COMPANIES]->()-[:HAS_COMPANY]->company, company--foo RETURN company, collect(foo) as Bar",
                new Dictionary<string, object>(),
                CypherResultMode.Projection,
                CypherResultFormat.Rest);

            var cypherApiQuery = new CypherApiQuery(cypherQuery);

            using (var testHarness = new RestTestHarness
                {
                    {
                        MockRequest.PostObjectAsJson("/cypher", cypherApiQuery),
                        MockResponse.Json(HttpStatusCode.OK, @"{
  'columns' : [ 'ColumnA', 'ColumnBFromCollect' ],
  'data' : [ [ {
    'paged_traverse' : 'http://localhost:8000/db/data/node/358/paged/traverse/{returnType}{?pageSize,leaseTime}',
    'outgoing_relationships' : 'http://localhost:8000/db/data/node/358/relationships/out',
    'data' : {
      'Bar' : 'BHP',
      'Baz' : '1'
    },
    'all_typed_relationships' : 'http://localhost:8000/db/data/node/358/relationships/all/{-list|&|types}',
    'traverse' : 'http://localhost:8000/db/data/node/358/traverse/{returnType}',
    'self' : 'http://localhost:8000/db/data/node/358',
    'property' : 'http://localhost:8000/db/data/node/358/properties/{key}',
    'all_relationships' : 'http://localhost:8000/db/data/node/358/relationships/all',
    'outgoing_typed_relationships' : 'http://localhost:8000/db/data/node/358/relationships/out/{-list|&|types}',
    'properties' : 'http://localhost:8000/db/data/node/358/properties',
    'incoming_relationships' : 'http://localhost:8000/db/data/node/358/relationships/in',
    'incoming_typed_relationships' : 'http://localhost:8000/db/data/node/358/relationships/in/{-list|&|types}',
    'extensions' : {
    },
    'create_relationship' : 'http://localhost:8000/db/data/node/358/relationships'
  }, [ {
    'paged_traverse' : 'http://localhost:8000/db/data/node/362/paged/traverse/{returnType}{?pageSize,leaseTime}',
    'outgoing_relationships' : 'http://localhost:8000/db/data/node/362/relationships/out',
    'data' : {
      'OpportunityType' : 'Board',
      'Description' : 'Foo'
    },
    'all_typed_relationships' : 'http://localhost:8000/db/data/node/362/relationships/all/{-list|&|types}',
    'traverse' : 'http://localhost:8000/db/data/node/362/traverse/{returnType}',
    'self' : 'http://localhost:8000/db/data/node/362',
    'property' : 'http://localhost:8000/db/data/node/362/properties/{key}',
    'all_relationships' : 'http://localhost:8000/db/data/node/362/relationships/all',
    'outgoing_typed_relationships' : 'http://localhost:8000/db/data/node/362/relationships/out/{-list|&|types}',
    'properties' : 'http://localhost:8000/db/data/node/362/properties',
    'incoming_relationships' : 'http://localhost:8000/db/data/node/362/relationships/in',
    'incoming_typed_relationships' : 'http://localhost:8000/db/data/node/362/relationships/in/{-list|&|types}',
    'extensions' : {
    },
    'create_relationship' : 'http://localhost:8000/db/data/node/362/relationships'
  }, {
    'paged_traverse' : 'http://localhost:8000/db/data/node/359/paged/traverse/{returnType}{?pageSize,leaseTime}',
    'outgoing_relationships' : 'http://localhost:8000/db/data/node/359/relationships/out',
    'data' : {
      'OpportunityType' : 'Executive',
      'Description' : 'Bar'
    },
    'all_typed_relationships' : 'http://localhost:8000/db/data/node/359/relationships/all/{-list|&|types}',
    'traverse' : 'http://localhost:8000/db/data/node/359/traverse/{returnType}',
    'self' : 'http://localhost:8000/db/data/node/359',
    'property' : 'http://localhost:8000/db/data/node/359/properties/{key}',
    'all_relationships' : 'http://localhost:8000/db/data/node/359/relationships/all',
    'outgoing_typed_relationships' : 'http://localhost:8000/db/data/node/359/relationships/out/{-list|&|types}',
    'properties' : 'http://localhost:8000/db/data/node/359/properties',
    'incoming_relationships' : 'http://localhost:8000/db/data/node/359/relationships/in',
    'incoming_typed_relationships' : 'http://localhost:8000/db/data/node/359/relationships/in/{-list|&|types}',
    'extensions' : {
    },
    'create_relationship' : 'http://localhost:8000/db/data/node/359/relationships'
  } ] ] ]
}")
                    }
                })
            {
                var graphClient = testHarness.CreateAndConnectGraphClient();

                //Act
                var results = graphClient.ExecuteGetCypherResults<CollectResult>(cypherQuery);

                //Assert
                Assert.IsInstanceOf<IEnumerable<CollectResult>>(results);

                var resultsArray = results.ToArray();
                Assert.AreEqual(1, resultsArray.Count());

                var firstResult = resultsArray[0];
                Assert.AreEqual(358, firstResult.ColumnA.Reference.Id);
                Assert.AreEqual("BHP", firstResult.ColumnA.Data.Bar);
                Assert.AreEqual("1", firstResult.ColumnA.Data.Baz);

                var collectedResults = firstResult.ColumnBFromCollect.ToArray();
                Assert.AreEqual(2, collectedResults.Count());

                var firstCollectedResult = collectedResults[0];
                Assert.AreEqual(362, firstCollectedResult.Reference.Id);
                Assert.AreEqual("Board", firstCollectedResult.Data.OpportunityType);
                Assert.AreEqual("Foo", firstCollectedResult.Data.Description);

                var secondCollectedResult = collectedResults[1];
                Assert.AreEqual(359, secondCollectedResult.Reference.Id);
                Assert.AreEqual("Executive", secondCollectedResult.Data.OpportunityType);
                Assert.AreEqual("Bar", secondCollectedResult.Data.Description);
            }
        }
        public void DoesntSetHeaders_WhenNotSet()
        {
            const string queryText = "MATCH n SET n.Value = 'value'";

            var cypherQuery = new CypherQuery(queryText, new Dictionary<string, object>(), CypherResultMode.Set);
            var cypherApiQuery = new CypherApiQuery(cypherQuery);

            using (var testHarness = new RestTestHarness
            {
                {
                    MockRequest.Get(""),
                    MockResponse.NeoRoot()
                },
                {
                    MockRequest.PostObjectAsJson("/cypher", cypherApiQuery),
                    MockResponse.Http((int) HttpStatusCode.OK)
                }
            })
            {
                var httpClient = testHarness.GenerateHttpClient(testHarness.BaseUri);
                var graphClient = new GraphClient(new Uri(testHarness.BaseUri), httpClient);
                graphClient.Connect();

                httpClient.ClearReceivedCalls();
                ((IRawGraphClient)graphClient).ExecuteCypher(cypherQuery);

                var call = httpClient.ReceivedCalls().Single();
                var requestMessage = (HttpRequestMessage)call.GetArguments()[0];
                Assert.IsFalse(requestMessage.Headers.Any(h => h.Key == "max-execution-time"));
            }
        }
        public void SendsCommandWithCustomHeaders()
        {
            const string queryText = "MATCH n SET n.Value = 'value'";
            const int expectedMaxExecutionTime = 100;
            const string headerName = "MyTestHeader";
            const string headerValue = "myTestHeaderValue";
            var customHeaders = new NameValueCollection();
            customHeaders.Add(headerName, headerValue);

            var cypherQuery = new CypherQuery(queryText, new Dictionary<string, object>(), CypherResultMode.Set, CypherResultFormat.DependsOnEnvironment, maxExecutionTime: expectedMaxExecutionTime, customHeaders: customHeaders);
            
            var cypherApiQuery = new CypherApiQuery(cypherQuery);

            using (var testHarness = new RestTestHarness
            {
                {
                    MockRequest.Get(""),
                    MockResponse.NeoRoot()
                },
                {
                    MockRequest.PostObjectAsJson("/cypher", cypherApiQuery),
                    MockResponse.Http((int) HttpStatusCode.OK)
                }
            })
            {
                var httpClient = testHarness.GenerateHttpClient(testHarness.BaseUri);
                var graphClient = new GraphClient(new Uri(testHarness.BaseUri), httpClient);
                graphClient.Connect();

                httpClient.ClearReceivedCalls();
                ((IRawGraphClient)graphClient).ExecuteCypher(cypherQuery);

                var call = httpClient.ReceivedCalls().Single();
                var requestMessage = (HttpRequestMessage)call.GetArguments()[0];
                var maxExecutionTimeHeader = requestMessage.Headers.Single(h => h.Key == "max-execution-time");
                Assert.AreEqual(expectedMaxExecutionTime.ToString(CultureInfo.InvariantCulture), maxExecutionTimeHeader.Value.Single());
                var customHeader = requestMessage.Headers.Single(h => h.Key == headerName);
                Assert.IsNotNull(customHeader);
                Assert.AreEqual(headerValue, customHeader.Value.Single());
            }
        }
        public void ShouldDeserializeTableStructureWithRelationships()
        {
            // Arrange
            const string queryText = @"
                START x = node({p0})
                MATCH x-[r]->n
                RETURN x AS Fooness, type(r) AS RelationshipType, n.Name? AS Name, n.UniqueId? AS UniqueId
                LIMIT 3";
            var cypherQuery = new CypherQuery(
                queryText,
                new Dictionary<string, object>
                {
                    {"p0", 123}
                },
                CypherResultMode.Projection,
                CypherResultFormat.Rest);

            var cypherApiQuery = new CypherApiQuery(cypherQuery);

            using (var testHarness = new RestTestHarness
                {
                    {
                        MockRequest.PostObjectAsJson("/cypher", cypherApiQuery),
                        MockResponse.Json(HttpStatusCode.OK, @"{
                                'data' : [ [ {
                                'start' : 'http://foo/db/data/node/0',
                                'data' : {
                                    'Bar' : 'bar',
                                    'Baz' : 'baz'
                                },
                                'property' : 'http://foo/db/data/relationship/0/properties/{key}',
                                'self' : 'http://foo/db/data/relationship/0',
                                'properties' : 'http://foo/db/data/relationship/0/properties',
                                'type' : 'HAS_REFERENCE_DATA',
                                'extensions' : {
                                },
                                'end' : 'http://foo/db/data/node/1'
                                }, 'HOSTS', 'foo', 44321 ], [ {
                                'start' : 'http://foo/db/data/node/1',
                                'data' : {
                                    'Bar' : 'bar',
                                    'Baz' : 'baz'
                                },
                                'property' : 'http://foo/db/data/relationship/1/properties/{key}',
                                'self' : 'http://foo/db/data/relationship/1',
                                'properties' : 'http://foo/db/data/relationship/1/properties',
                                'type' : 'HAS_REFERENCE_DATA',
                                'extensions' : {
                                },
                                'end' : 'http://foo/db/data/node/1'
                                }, 'LIKES', 'bar', 44311 ], [ {
                                'start' : 'http://foo/db/data/node/2',
                                'data' : {
                                    'Bar' : 'bar',
                                    'Baz' : 'baz'
                                },
                                'property' : 'http://foo/db/data/relationship/2/properties/{key}',
                                'self' : 'http://foo/db/data/relationship/2',
                                'properties' : 'http://foo/db/data/relationship/2/properties',
                                'type' : 'HAS_REFERENCE_DATA',
                                'extensions' : {
                                },
                                'end' : 'http://foo/db/data/node/1'
                                }, 'HOSTS', 'baz', 42586 ] ],
                                'columns' : [ 'Fooness', 'RelationshipType', 'Name', 'UniqueId' ]
                            }")
                    }
                })
            {
                var graphClient = testHarness.CreateAndConnectGraphClient();

                //Act
                //Act
                var results = graphClient.ExecuteGetCypherResults<ResultWithRelationshipDto>(cypherQuery);

                //Assert
                Assert.IsInstanceOf<IEnumerable<ResultWithRelationshipDto>>(results);

                var resultsArray = results.ToArray();
                Assert.AreEqual(3, resultsArray.Count());

                var firstResult = resultsArray[0];
                Assert.AreEqual(0, firstResult.Fooness.Reference.Id);
                Assert.AreEqual("bar", firstResult.Fooness.Data.Bar);
                Assert.AreEqual("baz", firstResult.Fooness.Data.Baz);
                Assert.AreEqual("HOSTS", firstResult.RelationshipType);
                Assert.AreEqual("foo", firstResult.Name);
                Assert.AreEqual(44321, firstResult.UniqueId);

                var secondResult = resultsArray[1];
                Assert.AreEqual(1, secondResult.Fooness.Reference.Id);
                Assert.AreEqual("bar", secondResult.Fooness.Data.Bar);
                Assert.AreEqual("baz", secondResult.Fooness.Data.Baz);
                Assert.AreEqual("LIKES", secondResult.RelationshipType);
                Assert.AreEqual("bar", secondResult.Name);
                Assert.AreEqual(44311, secondResult.UniqueId);

                var thirdResult = resultsArray[2];
                Assert.AreEqual(2, thirdResult.Fooness.Reference.Id);
                Assert.AreEqual("bar", thirdResult.Fooness.Data.Bar);
                Assert.AreEqual("baz", thirdResult.Fooness.Data.Baz);
                Assert.AreEqual("HOSTS", thirdResult.RelationshipType);
                Assert.AreEqual("baz", thirdResult.Name);
                Assert.AreEqual(42586, thirdResult.UniqueId);
            }
        }
        public void SendsCommandWithCorrectTimeout()
        {
            const int expectedMaxExecutionTime = 100;

            const string queryText = @"START d=node({p0}), e=node({p1})
                                        MATCH p = allShortestPaths( d-[*..15]-e )
                                        RETURN p";

            var parameters = new Dictionary<string, object>
                {
                    {"p0", 215},
                    {"p1", 219}
                };


            var cypherQuery = new CypherQuery(queryText, parameters, CypherResultMode.Set,CypherResultFormat.Transactional ,maxExecutionTime: expectedMaxExecutionTime);
            var cypherApiQuery = new CypherApiQuery(cypherQuery);

            using (var testHarness = new RestTestHarness
            {
                {
                    MockRequest.Get(""),
                    MockResponse.NeoRoot()
                },
                {
                    MockRequest.PostObjectAsJson("/cypher", cypherApiQuery),
                    MockResponse.Json(HttpStatusCode.OK,
                    @"{
                              'data' : [ [ {
                                'start' : 'http://foo/db/data/node/215',
                                'nodes' : [ 'http://foo/db/data/node/215', 'http://foo/db/data/node/0', 'http://foo/db/data/node/219' ],
                                'length' : 2,
                                'relationships' : [ 'http://foo/db/data/relationship/247', 'http://foo/db/data/relationship/257' ],
                                'end' : 'http://foo/db/data/node/219'
                              } ], [ {
                                'start' : 'http://foo/db/data/node/215',
                                'nodes' : [ 'http://foo/db/data/node/215', 'http://foo/db/data/node/1', 'http://foo/db/data/node/219' ],
                                'length' : 2,
                                'relationships' : [ 'http://foo/db/data/relationship/248', 'http://foo/db/data/relationship/258' ],
                                'end' : 'http://foo/db/data/node/219'
                              } ] ],
                              'columns' : [ 'p' ]
                            }")
                }
            })
            {
                var httpClient = testHarness.GenerateHttpClient(testHarness.BaseUri);
                var graphClient = new GraphClient(new Uri(testHarness.BaseUri), httpClient);
                graphClient.Connect();

                httpClient.ClearReceivedCalls();
                ((IRawGraphClient)graphClient).ExecuteGetCypherResults<object>(cypherQuery);

                var call = httpClient.ReceivedCalls().Single();
                var requestMessage = (HttpRequestMessage)call.GetArguments()[0];
                var maxExecutionTimeHeader = requestMessage.Headers.Single(h => h.Key == "max-execution-time");
                Assert.AreEqual(expectedMaxExecutionTime.ToString(CultureInfo.InvariantCulture), maxExecutionTimeHeader.Value.Single());
            }
        }