public void EmptyCollectionShouldDeserializeCorrectly() { const string queryText = @"RETURN [] AS p"; var cypherQuery = new CypherQuery(queryText, new Dictionary <string, object>(), CypherResultMode.Set, CypherResultFormat.Rest); var cypherApiQuery = new CypherApiQuery(cypherQuery); using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/cypher", cypherApiQuery), MockResponse.Json(HttpStatusCode.OK, @"{'columns' : [ 'p' ], 'data' : [[ ]]}") } }) { var graphClient = testHarness.CreateAndConnectGraphClient(); var results = graphClient .ExecuteGetCypherResults <PathsResult>(cypherQuery) .ToArray(); Assert.Empty(results); } }
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.True(t.IsFaulted); Assert.IsAssignableFrom <MockResponseThrowsException>(t.Exception.Flatten().InnerException); }); task.Wait(); Assert.False(raisedEvent, "Raised OperationCompleted"); } }
public void CommitFailsOnPendingAsyncRequests() { const string queryText = @"MATCH (n) RETURN count(n) as Total"; const string resultColumn = @"{'columns':['Total'], 'data':[{'row':[1]}]}"; var cypherQuery = new CypherQuery(queryText, new Dictionary <string, object>(), CypherResultMode.Projection); var cypherApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery, false) }; using (var testHarness = new RestTestHarness(false) { { MockRequest.PostObjectAsJson("/transaction", cypherApiQuery), MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1, resultColumn), "http://foo/db/data/transaction/1") } }) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); var rawClient = (IRawGraphClient)client; using (var tran = client.BeginTransaction()) { rawClient.ExecuteGetCypherResultsAsync <DummyTotal>(cypherQuery); tran.Commit(); } } }
public async Task EmptyCollectionShouldDeserializeCorrectly() { const string queryText = @"RETURN [] AS p"; var cypherQuery = new CypherQuery(queryText, new Dictionary <string, object>(), CypherResultMode.Set, CypherResultFormat.Rest, "neo4j"); var cypherApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery) }; using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/transaction/commit", cypherApiQuery), MockResponse.Json(HttpStatusCode.OK, @"{'results': [{'columns' : [ 'p' ], 'data' : []}]}") } }) { var graphClient = await testHarness.CreateAndConnectGraphClient(); var results = (await graphClient .ExecuteGetCypherResultsAsync <PathsResult>(cypherQuery)) .ToArray(); Assert.Empty(results); } }
public void ShouldPromoteBadQueryResponseToNiceException() { // Arrange const string queryText = @"broken query"; var cypherQuery = new CypherQuery(queryText, new Dictionary <string, object>(), CypherResultMode.Projection); var cypherApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery, false) }; using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/transaction", cypherApiQuery), MockResponse.Json(HttpStatusCode.OK, @"{'results':[], 'errors': [{ 'code' : 'Neo.ClientError.Statement.InvalidSyntax', 'message' : 'Invalid input b: expected SingleStatement (line 1, column 1)\nThis is not a valid Cypher Statement.\n ^' }]}") } }) { var graphClient = testHarness.CreateAndConnectTransactionalGraphClient(); var rawClient = (IRawGraphClient)graphClient; using (graphClient.BeginTransaction()) { var ex = Assert.Throws <NeoException>(() => rawClient.ExecuteCypher(cypherQuery)); Assert.AreEqual("InvalidSyntax: Invalid input b: expected SingleStatement (line 1, column 1)\nThis is not a valid Cypher Statement.\n ^", ex.Message); Assert.AreEqual("Invalid input b: expected SingleStatement (line 1, column 1)\nThis is not a valid Cypher Statement.\n ^", ex.NeoMessage); Assert.AreEqual("InvalidSyntax", ex.NeoExceptionName); Assert.AreEqual("Neo.ClientError.Statement.InvalidSyntax", ex.NeoFullName); CollectionAssert.AreEqual(new String[] {}, ex.NeoStackTrace); } } }
public void SendsCommandWithCorrectTimeout() { const string queryText = "MATCH n SET n.Value = 'value'"; const int expectedMaxExecutionTime = 100; var cypherQuery = new CypherQuery(queryText, new Dictionary <string, object>(), CypherResultMode.Set, CypherResultFormat.DependsOnEnvironment, maxExecutionTime: expectedMaxExecutionTime); 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.Equal(expectedMaxExecutionTime.ToString(CultureInfo.InvariantCulture), maxExecutionTimeHeader.Value.Single()); } }
public async Task CommitFailsOnPendingAsyncRequests() { const string queryText = @"MATCH (n) RETURN count(n) as Total"; const string resultColumn = @"{'columns':['Total'], 'data':[{'row':[1]}]}"; var cypherQuery = new CypherQuery(queryText, new Dictionary <string, object>(), CypherResultMode.Projection, "neo4j"); var cypherApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery) }; using (var testHarness = new RestTestHarness(false) { { MockRequest.PostObjectAsJson("/transaction", cypherApiQuery), MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1, resultColumn), "http://foo/db/data/transaction/1") } }) { var client = await testHarness.CreateAndConnectTransactionalGraphClient(); var rawClient = (IRawGraphClient)client; using (var tran = client.BeginTransaction()) { await rawClient.ExecuteGetCypherResultsAsync <DummyTotal>(cypherQuery); var ex = await Assert.ThrowsAsync <InvalidOperationException>(async() => await tran.CommitAsync()); Assert.Equal("Cannot commit unless all tasks have been completed", ex.Message); } } }
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.True(raisedEvent, "Raised OperationCompleted"); } }
public void ShouldReturnEmptyEnumerableForNullResult() { //Arrange const string gremlinQueryExpected = "foo bar query"; var query = new GremlinApiQuery(gremlinQueryExpected, null); using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/ext/GremlinPlugin/graphdb/execute_script", query), MockResponse.Json(HttpStatusCode.OK, @"[]") } }) { var graphClient = (GraphClient)testHarness.CreateAndConnectGraphClient(); //Act var nodes = graphClient .ExecuteGetAllRelationshipsGremlin(gremlinQueryExpected, null) .ToList(); //Assert Assert.AreEqual(0, nodes.Count()); } }
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.False(requestMessage.Headers.Any(h => h.Key == "max-execution-time")); } }
public void ExecuteAsyncRequestInTransaction() { const string queryText = @"MATCH (n) RETURN count(n) as Total"; const string resultColumn = @"{'columns':['Total'], 'data':[{'row':[1]}]}"; var cypherQuery = new CypherQuery(queryText, new Dictionary <string, object>(), CypherResultMode.Projection); var cypherApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery, false) }; var commitRequest = MockRequest.PostJson("/transaction/1/commit", @"{'statements': []}"); using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/transaction", cypherApiQuery), MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1, resultColumn), "http://foo/db/data/transaction/1") }, { commitRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); var rawClient = (IRawGraphClient)client; using (var tran = client.BeginTransaction()) { var totalObj = rawClient.ExecuteGetCypherResultsAsync <DummyTotal>(cypherQuery).Result.Single(); Assert.AreEqual(1, totalObj.Total); tran.Commit(); } } }
public async Task DoesntSetMaxExecutionTime_WhenNotSet() { const string queryText = "MATCH n SET n.Value = 'value'"; var cypherQuery = new CypherQuery(queryText, new Dictionary <string, object>(), CypherResultMode.Set, "neo4j"); var transactionApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery) }; using (var testHarness = new RestTestHarness { { MockRequest.Get(""), MockResponse.NeoRoot20() }, { MockRequest.PostObjectAsJson("/transaction/commit", transactionApiQuery), MockResponse.Http((int)HttpStatusCode.OK) } }) { var httpClient = testHarness.GenerateHttpClient(testHarness.BaseUri); var graphClient = new GraphClient(new Uri(testHarness.BaseUri), httpClient); await graphClient.ConnectAsync(); httpClient.ClearReceivedCalls(); await((IRawGraphClient)graphClient).ExecuteCypherAsync(cypherQuery); var call = httpClient.ReceivedCalls().Single(); var requestMessage = (HttpRequestMessage)call.GetArguments()[0]; Assert.False(requestMessage.Headers.Any(h => h.Key == "max-execution-time")); } }
public async Task 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, CypherResultFormat.Rest, "neo4j"); var transactionApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery) }; using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/transaction/commit", transactionApiQuery), MockResponse.Http((int)HttpStatusCode.OK) } }) { var graphClient = await testHarness.CreateAndConnectGraphClient(); //Act await graphClient.ExecuteCypherAsync(cypherQuery); } }
public async Task WhenExecuteCypherFails_ShouldRaiseCompletedWithException() { // Arrange const string queryText = @"bad cypher"; var parameters = new Dictionary <string, object>(); var cypherQuery = new CypherQuery(queryText, parameters, CypherResultMode.Set, "neo4j"); var transactionApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery) }; using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/transaction/commit", transactionApiQuery), MockResponse.Throws() } }) { var graphClient = await testHarness.CreateAndConnectGraphClient(); OperationCompletedEventArgs eventArgs = null; graphClient.OperationCompleted += (sender, e) => { eventArgs = e; }; //Act await Assert.ThrowsAsync <MockResponseThrowsException>(async() => { await graphClient.ExecuteCypherAsync(cypherQuery); }); Assert.NotNull(eventArgs); Assert.True(eventArgs.HasException); Assert.Equal(typeof(MockResponseThrowsException), eventArgs.Exception.GetType()); Assert.Equal(-1, eventArgs.ResourcesReturned); } }
public async Task ThrowsClientException_WhenGettingErrorResponse() { const string queryText = @"return 1"; var parameters = new Dictionary <string, object>(); var cypherQuery = new CypherQuery(queryText, parameters, CypherResultMode.Set, "neo4j"); var transactionApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery) }; using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/transaction/commit", transactionApiQuery), EmptyErrorResponse } }) { var graphClient = await testHarness.CreateAndConnectGraphClient(); //Act var ex = await Assert.ThrowsAsync <ClientException>(async() => await graphClient.ExecuteCypherAsync(cypherQuery)); ex.Code.Should().Be("Error 1"); ex.Message.Should().Be("Unable to do Cypher"); } }
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, 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(); //Act graphClient.ExecuteCypher(cypherQuery); } }
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); }); Assert.NotNull(eventArgs); Assert.True(eventArgs.HasException); Assert.Equal(typeof(MockResponseThrowsException), eventArgs.Exception.GetType()); Assert.Equal(-1, eventArgs.ResourcesReturned); } }
public void WhenExecuteGetCypherResultsFails_ShouldRaiseCompletedWithException() { // 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(); OperationCompletedEventArgs eventArgs = null; graphClient.OperationCompleted += (sender, e) => { eventArgs = e; }; //Act Assert.Throws <MockResponseThrowsException>(() => { graphClient.ExecuteGetCypherResults <ExecuteGetCypherResultsTests.SimpleResultDto>(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 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.Equal(expectedMaxExecutionTime.ToString(CultureInfo.InvariantCulture), maxExecutionTimeHeader.Value.Single()); } }
public async Task 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, "neo4j"); var cypherApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery) }; using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/transaction/commit", 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 = await testHarness.CreateAndConnectGraphClient(); //Act var results = (await graphClient .ExecuteGetCypherResultsAsync <PathsResult>(cypherQuery)) .ToArray(); //Assert Assert.IsAssignableFrom <IEnumerable <PathsResult> >(results); Assert.Equal(results.First().Length, 2); Assert.Equal(results.First().Start, "http://foo/db/data/node/215"); Assert.Equal(results.First().End, "http://foo/db/data/node/219"); Assert.Equal(results.Skip(1).First().Length, 2); Assert.Equal(results.Skip(1).First().Start, "http://foo/db/data/node/215"); Assert.Equal(results.Skip(1).First().End, "http://foo/db/data/node/219"); } }
public async Task 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, "neo4j"); var cypherApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery) }; using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/transaction/commit", cypherApiQuery), MockResponse.Json(HttpStatusCode.OK, @"{ 'data' : [ [ 'HOSTS', 'foo', 44321 ], [ 'LIKES', 'bar', 44311 ], [ 'HOSTS', 'baz', 42586 ] ], 'columns' : [ 'RelationshipType', 'Name', 'UniqueId' ] }") } }) { var graphClient = await testHarness.CreateAndConnectGraphClient(); //Act var results = await graphClient.ExecuteGetCypherResultsAsync <SimpleResultDto>(cypherQuery); //Assert Assert.IsAssignableFrom <IEnumerable <SimpleResultDto> >(results); var resultsArray = results.ToArray(); Assert.Equal(3, resultsArray.Count()); var firstResult = resultsArray[0]; Assert.Equal("HOSTS", firstResult.RelationshipType); Assert.Equal("foo", firstResult.Name); Assert.Equal(44321, firstResult.UniqueId); var secondResult = resultsArray[1]; Assert.Equal("LIKES", secondResult.RelationshipType); Assert.Equal("bar", secondResult.Name); Assert.Equal(44311, secondResult.UniqueId); var thirdResult = resultsArray[2]; Assert.Equal("HOSTS", thirdResult.RelationshipType); Assert.Equal("baz", thirdResult.Name); Assert.Equal(42586, thirdResult.UniqueId); } }
public async Task 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, "neo4j"); var cypherApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery) }; using (var testHarness = new RestTestHarness { { MockRequest.Get(""), MockResponse.NeoRoot20() }, { MockRequest.PostObjectAsJson("/transaction/commit", 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); await graphClient.ConnectAsync(); httpClient.ClearReceivedCalls(); await((IRawGraphClient)graphClient).ExecuteGetCypherResultsAsync <object>(cypherQuery); var call = httpClient.ReceivedCalls().Single(); var requestMessage = (HttpRequestMessage)call.GetArguments()[0]; Assert.False(requestMessage.Headers.Any(h => h.Key == "max-execution-time")); } }
[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); 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 NestedTransactionMixedBetweenTransactionScopeAndBeginTransaction() { const string queryText = @"MATCH (n) RETURN count(n)"; const string resultColumn = @"{'columns':['count(n)'], 'data':[{'row':[1]}]}"; var cypherQuery = new CypherQuery(queryText, new Dictionary <string, object>(), CypherResultMode.Projection); var cypherApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery, false) }; var deleteRequest = MockRequest.Delete("/transaction/1"); var commitRequest = MockRequest.PostJson("/transaction/1/commit", @"{'statements': []}"); using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/transaction", cypherApiQuery), MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1, resultColumn), "http://foo/db/data/transaction/1") }, { commitRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") }, { deleteRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }.ShouldNotBeCalled(commitRequest)) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var parentTx = client.BeginTransaction()) { using (var msTransaction = new TransactionScope()) { Assert.IsTrue(client.InTransaction); using (var tx = client.BeginTransaction()) { long total = client.Cypher .Match("(n)") .Return(n => n.Count()) .Results .SingleOrDefault(); Assert.AreEqual(1, total); // should not be called tx.Commit(); } msTransaction.Complete(); } } Assert.IsFalse(client.InTransaction); } }
public void ShouldNotThrowANotSupportedExceptionForPre15M02DatabaseWhenThereAreNoIndexEntries() { var testNode = new TestNode { Foo = "foo", Bar = "bar", Baz = "baz" }; var batch = new List <BatchStep>(); batch.Add(HttpMethod.Post, "/node", testNode); var testHarness = new RestTestHarness { { MockRequest.Get(""), MockResponse.NeoRootPre15M02() }, { MockRequest.PostObjectAsJson("/batch", batch), MockResponse.Json(HttpStatusCode.OK, @"[{'id':0,'location':'http://foo/db/data/node/760','body':{ 'outgoing_relationships' : 'http://foo/db/data/node/760/relationships/out', 'data' : { 'Foo' : 'foo', 'Bar' : 'bar', 'Baz' : 'baz' }, 'traverse' : 'http://foo/db/data/node/760/traverse/{returnType}', 'all_typed_relationships' : 'http://foo/db/data/node/760/relationships/all/{-list|&|types}', 'self' : 'http://foo/db/data/node/760', 'property' : 'http://foo/db/data/node/760/properties/{key}', 'outgoing_typed_relationships' : 'http://foo/db/data/node/760/relationships/out/{-list|&|types}', 'properties' : 'http://foo/db/data/node/760/properties', 'incoming_relationships' : 'http://foo/db/data/node/760/relationships/in', 'extensions' : { }, 'create_relationship' : 'http://foo/db/data/node/760/relationships', 'paged_traverse' : 'http://foo/db/data/node/760/paged/traverse/{returnType}{?pageSize,leaseTime}', 'all_relationships' : 'http://foo/db/data/node/760/relationships/all', 'incoming_typed_relationships' : 'http://foo/db/data/node/760/relationships/in/{-list|&|types}' },'from':'/node'}]" ) } }; var graphClient = testHarness.CreateAndConnectGraphClient(); graphClient.Create(testNode, null, null); testHarness.AssertRequestConstraintsAreMet(); }
public async Task ShouldPromoteBadQueryResponseToNiceException() { // Arrange const string queryText = @"broken query"; var cypherQuery = new CypherQuery(queryText, new Dictionary <string, object>(), CypherResultMode.Projection, CypherResultFormat.Rest, "neo4j"); var cypherApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery) }; using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/transaction/commit", 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 = await testHarness.CreateAndConnectGraphClient(); var ex = await Assert.ThrowsAsync <NeoException>(async() => await graphClient.ExecuteGetCypherResultsAsync <ResultWithRelationshipDto>(cypherQuery)); Assert.Equal("SyntaxException: expected START or CREATE\n'bad query'\n ^", ex.Message); Assert.Equal("expected START or CREATE\n'bad query'\n ^", ex.NeoMessage); Assert.Equal("SyntaxException", ex.NeoExceptionName); Assert.Equal("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)" }; Assert.Equal(expectedStack, ex.NeoStackTrace); } }
public void TestTransactionScopeWithComplexDeserialization_WithCulture() { Thread.CurrentThread.CurrentCulture = new CultureInfo("nb-NO"); const string queryText = @"MATCH (dt:DummyTotal) RETURN dt"; const string resultColumn = @"{'columns':['dt'],'data':[{'row':[{'date':'2015-07-27T22:30:35Z'}]}]}"; var cypherQuery = new CypherQuery(queryText, new Dictionary <string, object>(), CypherResultMode.Projection); var cypherApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery, false) }; var commitRequest = MockRequest.PostJson("/transaction/1/commit", @"{'statements': []}"); using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/transaction", cypherApiQuery), MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1, resultColumn), "http://foo/db/data/transaction/1") }, { commitRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); client.JsonContractResolver = new CamelCasePropertyNamesContractResolver(); using (var msTransaction = new TransactionScope()) { Assert.IsTrue(client.InTransaction); var query = client.Cypher.Match("(dt:DummyTotal)") .Return(dt => dt.As <DateHolder>()); var eResults = query.Results; var results = eResults.ToList(); Assert.AreEqual(1, results.Count); var date = results.First().Date; Assert.AreEqual(date.Kind, DateTimeKind.Utc); Assert.AreEqual(new DateTime(2015, 7, 27, 22, 30, 35), results.First().Date); msTransaction.Complete(); } Assert.IsFalse(client.InTransaction); } }
public void ShouldReturnReferenceToCreatedNodeWithLongId() { var testNode = new TestNode { Foo = "foo", Bar = "bar", Baz = "baz" }; var batch = new List <BatchStep>(); batch.Add(HttpMethod.Post, "/node", testNode); var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/batch", batch), MockResponse.Json(HttpStatusCode.OK, @"[{'id':0,'location':'http://foo/db/data/node/2157483647','body':{ 'outgoing_relationships' : 'http://foo/db/data/node/2157483647/relationships/out', 'data' : { 'Foo' : 'foo', 'Bar' : 'bar', 'Baz' : 'baz' }, 'traverse' : 'http://foo/db/data/node/2157483647/traverse/{returnType}', 'all_typed_relationships' : 'http://foo/db/data/node/2157483647/relationships/all/{-list|&|types}', 'self' : 'http://foo/db/data/node/2157483647', 'property' : 'http://foo/db/data/node/2157483647/properties/{key}', 'outgoing_typed_relationships' : 'http://foo/db/data/node/2157483647/relationships/out/{-list|&|types}', 'properties' : 'http://foo/db/data/node/2157483647/properties', 'incoming_relationships' : 'http://foo/db/data/node/2157483647/relationships/in', 'extensions' : { }, 'create_relationship' : 'http://foo/db/data/node/2157483647/relationships', 'paged_traverse' : 'http://foo/db/data/node/2157483647/paged/traverse/{returnType}{?pageSize,leaseTime}', 'all_relationships' : 'http://foo/db/data/node/2157483647/relationships/all', 'incoming_typed_relationships' : 'http://foo/db/data/node/2157483647/relationships/in/{-list|&|types}' },'from':'/node'}]" ) } }; var graphClient = testHarness.CreateAndConnectGraphClient(); var node = graphClient.Create(testNode); Assert.AreEqual(2157483647, node.Id); testHarness.AssertRequestConstraintsAreMet(); }
public void ShouldPreserveSlashInRelationshipIndexValue() { //Arrange var indexKeyValues = new Dictionary <string, object> { { "BarKey", "abc/def" } }; var indexEntries = new List <IndexEntry> { new IndexEntry { Name = "my_relationships", KeyValues = indexKeyValues, } }; using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/index/relationship/my_relationships", new { key = "BarKey", value = "abc/def", uri = "http://foo/db/data/relationship/123" }), MockResponse.Json(HttpStatusCode.Created, @"Location: http://foo/db/data/index/relationship/my_relationships/BarKey/abc-def/1234") }, { MockRequest.Delete("/index/relationship/my_relationships/123"), MockResponse.Http((int)HttpStatusCode.NoContent) } }) { var graphClient = testHarness.CreateAndConnectGraphClient(); //Act var relReference = new RelationshipReference(123); graphClient.ReIndex(relReference, indexEntries); // Assert Assert.Pass("Success."); } }
public void ShouldReturnListOfRelationshipInstancesWithPayloads() { //Arrange const string gremlinQueryExpected = "foo bar query"; var query = new GremlinApiQuery(gremlinQueryExpected, null); using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/ext/GremlinPlugin/graphdb/execute_script", query), MockResponse.Json(HttpStatusCode.OK, @"[ { 'start' : 'http://127.0.0.1:5118/db/data/node/123', 'data' : { 'Foo': 'Foo', 'Bar': 'Bar' }, 'self' : 'http://127.0.0.1:5118/db/data/relationship/456', 'property' : 'http://127.0.0.1:5118/db/data/relationship/456/properties/{key}', 'properties' : 'http://127.0.0.1:5118/db/data/relationship/456/properties', 'type' : 'KNOWS', 'extensions' : { }, 'end' : 'http://127.0.0.1:5118/db/data/node/789' } ]") } }) { var graphClient = (GraphClient)testHarness.CreateAndConnectGraphClient(); //Act var relationships = graphClient .ExecuteGetAllRelationshipsGremlin <TestPayload>(gremlinQueryExpected, null) .ToList(); //Assert Assert.AreEqual(1, relationships.Count()); Assert.AreEqual(456, relationships.ElementAt(0).Reference.Id); Assert.AreEqual(123, relationships.ElementAt(0).StartNodeReference.Id); Assert.AreEqual(789, relationships.ElementAt(0).EndNodeReference.Id); Assert.AreEqual("KNOWS", relationships.ElementAt(0).TypeKey); Assert.AreEqual("Foo", relationships.ElementAt(0).Data.Foo); Assert.AreEqual("Bar", relationships.ElementAt(0).Data.Bar); } }