public async Task ShouldSendCommandAndNotCareAboutResultsAsync() { // Arrange 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), MockResponse.Http((int)HttpStatusCode.OK) } }) { var graphClient = await testHarness.CreateAndConnectGraphClient(); var raisedEvent = false; graphClient.OperationCompleted += (sender, e) => { raisedEvent = true; }; //Act var task = graphClient.ExecuteCypherAsync(cypherQuery); task.Wait(); Assert.True(raisedEvent, "Raised OperationCompleted"); } }
public async Task DoesntSetHeaders_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 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 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, "neo4j", maxExecutionTime: expectedMaxExecutionTime); 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]; var maxExecutionTimeHeader = requestMessage.Headers.Single(h => h.Key == "max-execution-time"); Assert.Equal(expectedMaxExecutionTime.ToString(CultureInfo.InvariantCulture), maxExecutionTimeHeader.Value.Single()); } }
public async Task ReturnsQueryStats_WhenNotInTransaction() { var response = MockResponse.Json(200, @"{ 'results' : [ { 'columns' : [ 'id(n)' ], 'data' : [ { 'row' : [ 4 ], 'meta' : [ null ] } ], 'stats' : { 'contains_updates' : true, 'nodes_created' : 1, 'nodes_deleted' : 0, 'properties_set' : 0, 'relationships_created' : 0, 'relationship_deleted' : 0, 'labels_added' : 0, 'labels_removed' : 0, 'indexes_added' : 0, 'indexes_removed' : 0, 'constraints_added' : 0, 'constraints_removed' : 0, 'contains_system_updates' : false, 'system_updates' : 0 } } ], 'errors' : [ ] } "); const string queryText = @"MATCH (n) RETURN id(n)"; var cypherQuery = new CypherQuery(queryText, null, CypherResultMode.Set, CypherResultFormat.Rest, "neo4j", includeQueryStats: true); var transactionApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery) }; using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/transaction/commit", transactionApiQuery), response } }) { var graphClient = await testHarness.CreateAndConnectGraphClient(); var completedRaised = false; QueryStats stats = null; graphClient.OperationCompleted += (o, e) => { stats = e.QueryStats; completedRaised = true; }; var results = await graphClient.ExecuteGetCypherResultsAsync <int>(cypherQuery); results.First().Should().Be(4); completedRaised.Should().BeTrue(); stats.Should().NotBeNull(); stats.NodesCreated.Should().Be(1); } }
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 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 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 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 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 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 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 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")); } }
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 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 TestTransactionScopeWithComplexDeserialization() { const string queryText = @"MATCH (dt:DummyTotal) RETURN dt"; const string resultColumn = @"{'columns':['dt'],'data':[{'row':[{'total':1234}]}]}"; 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 results = client.Cypher.Match("(dt:DummyTotal)") .Return(dt => dt.As <DummyTotal>()) .Results .ToList(); Assert.AreEqual(1, results.Count()); Assert.AreEqual(1234, results.First().Total); msTransaction.Complete(); } Assert.IsFalse(client.InTransaction); } }
public void TestTransactionScopeWithSimpleDeserialization() { 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 commitRequest = MockRequest.PostJson("/transaction/1/commit", @"{'statements': []}"); using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/transaction", cypherApiQuery), MockResponse.Json(201, GenerateInitTransactionResponse(1, resultColumn), "http://foo/db/data/transaction/1") }, { commitRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var msTransaction = new TransactionScope()) { Assert.IsTrue(client.InTransaction); long total = client.Cypher .Match("(n)") .Return(n => n.Count()) .Results .SingleOrDefault(); Assert.AreEqual(1, total); msTransaction.Complete(); } Assert.IsFalse(client.InTransaction); } }
public async Task SendingNullParametersShouldNotRaiseExceptionWhenExecutingCypher() { const string queryText = @"MATCH (d) RETURN d"; var cypherQuery = new CypherQuery(queryText, null, 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(); // execute cypher with "null" parameters await graphClient.ExecuteCypherAsync(cypherQuery); } }
public async Task GraphClientFactoryUseCase() { const string queryText = @"RETURN d"; 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.Get("/"), MockResponse.NeoRoot20() }, { MockRequest.PostObjectAsJson("/transaction/commit", cypherApiQuery), new MockResponse { StatusCode = HttpStatusCode.OK } } }) { var httpClient = testHarness.GenerateHttpClient(testHarness.BaseUri); var executeConfiguration = new ExecutionConfiguration { HttpClient = httpClient, UserAgent = $"Neo4jClient/{typeof(NeoServerConfiguration).Assembly.GetName().Version}", UseJsonStreaming = true, JsonConverters = GraphClient.DefaultJsonConverters }; var configuration = await NeoServerConfiguration.GetConfigurationAsync(new Uri(testHarness.BaseUri), null, null, null, null, executeConfiguration); var factory = new GraphClientFactory(configuration); using (var client = await factory.CreateAsync(httpClient)) { await client.Cypher.Return <object>("d").ExecuteWithoutResultsAsync(); } } }
public void TestTransactionScopeWithSimpleDeserialization() { 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 commitRequest = MockRequest.PostJson("/transaction/1/commit", @"{'statements': []}"); using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/transaction", cypherApiQuery), MockResponse.Json(201, GenerateInitTransactionResponse(1, resultColumn), "http://foo/db/data/transaction/1") }, { commitRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var msTransaction = new TransactionScope()) { Assert.IsTrue(client.InTransaction); long total = client.Cypher .Match("(n)") .Return(n => n.Count()) .Results .SingleOrDefault(); Assert.AreEqual(1, total); msTransaction.Complete(); } Assert.IsFalse(client.InTransaction); } }
public void NestedTransactionWithTransactionScopeQueryFirst() { const string queryTextMsTransaction = @"MATCH (n) RETURN count(n)"; const string queryTextTx = @"MATCH (t) RETURN count(t)"; const string resultColumn = @"{'columns':['count(n)'], 'data':[{'row':[1]}]}"; var cypherQueryMsTx = new CypherQuery(queryTextMsTransaction, new Dictionary<string, object>(), CypherResultMode.Projection); var cypherQueryMsTxStatement = new CypherStatementList { new CypherTransactionStatement(cypherQueryMsTx, false) }; var cypherQueryTx = new CypherQuery(queryTextTx, new Dictionary<string, object>(), CypherResultMode.Projection); var cypherQueryTxStatement = new CypherStatementList { new CypherTransactionStatement(cypherQueryTx, false) }; var deleteRequest = MockRequest.Delete("/transaction/1"); var commitRequest = MockRequest.PostJson("/transaction/1/commit", @"{'statements': []}"); var commitRequestTx = MockRequest.PostJson("/transaction/2/commit", @"{'statements': []}"); using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/transaction", cypherQueryMsTxStatement), MockResponse.Json(201, GenerateInitTransactionResponse(1, resultColumn), "http://foo/db/data/transaction/1") }, { MockRequest.PostObjectAsJson("/transaction", cypherQueryTxStatement), MockResponse.Json(201, GenerateInitTransactionResponse(2, resultColumn), "http://foo/db/data/transaction/2") }, { commitRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") }, { commitRequestTx, MockResponse.Json(200, @"{'results':[], 'errors':[] }") }, { deleteRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }.ShouldNotBeCalled(commitRequest)) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var msTransaction = new TransactionScope()) { Assert.IsTrue(client.InTransaction); long totalMsTx = client.Cypher .Match("(n)") .Return(n => n.Count()) .Results .SingleOrDefault(); Assert.AreEqual(1, totalMsTx); using (var tx = client.BeginTransaction()) { long total = client.Cypher .Match("(t)") .Return(t => t.Count()) .Results .SingleOrDefault(); Assert.AreEqual(1, total); // should not be called tx.Commit(); } } } }
public void AsyncRequestsInTransactionShouldBeExecutedInOrder() { const string queryTextBase = @"MATCH (n) RETURN {0} as Total"; const string resultColumnBase = @"{{'columns':['Total'], 'data':[{{'row':[{0}]}}]}}"; const int asyncRequests = 15; var queries = new CypherQuery[asyncRequests]; var apiQueries = new CypherStatementList[asyncRequests]; var responses = new MockResponse[asyncRequests]; var testHarness = new RestHarnessWithCounter(); for (int i = 0; i < asyncRequests; i++) { queries[i] = new CypherQuery(string.Format(queryTextBase, i), new Dictionary<string, object>(), CypherResultMode.Projection); apiQueries[i] = new CypherStatementList {new CypherTransactionStatement(queries[i], false)}; responses[i] = MockResponse.Json(200, @"{'results':[" + string.Format(resultColumnBase, i) + @"], 'errors':[] }"); if (i > 0) { testHarness.Add(MockRequest.PostObjectAsJson("/transaction/1", apiQueries[i]), responses[i]); } } testHarness.Add( MockRequest.PostObjectAsJson("/transaction", apiQueries[0]), MockResponse.Json(201, GenerateInitTransactionResponse(1, string.Format(resultColumnBase, 0)), "http://foo/db/data/transaction/1") ); testHarness.Add( MockRequest.PostJson("/transaction/1/commit", @"{'statements': []}"), MockResponse.Json(200, @"{'results':[], 'errors':[] }") ); try { var client = testHarness.CreateAndConnectTransactionalGraphClient(); var rawClient = (IRawGraphClient)client; var tasks = new Task[asyncRequests]; using (var tran = client.BeginTransaction()) { for (int i = 0; i < asyncRequests; i++) { int tmpResult = i; tasks[i] = rawClient.ExecuteGetCypherResultsAsync<DummyTotal>(queries[i]).ContinueWith(task => { Assert.AreEqual(tmpResult, task.Result.Single().Total); }); } Task.WaitAll(tasks); tran.Commit(); } } finally { testHarness.Dispose(); } // check that we have a total order Assert.AreEqual(asyncRequests, testHarness.Queue.Count); int lastElement = -1; for (int i = 0; i < asyncRequests; i++) { int headItem; Assert.IsTrue(testHarness.Queue.TryDequeue(out headItem)); Assert.Greater(headItem, lastElement); lastElement = headItem; } }
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, 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 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, 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 void TestTransactionScopeWithComplexDeserialization() { const string queryText = @"MATCH (dt:DummyTotal) RETURN dt"; const string resultColumn = @"{'columns':['dt'],'data':[{'row':[{'total':1234}]}]}"; 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 results = client.Cypher.Match("(dt:DummyTotal)") .Return(dt => dt.As<DummyTotal>()) .Results .ToList(); Assert.AreEqual(1, results.Count()); Assert.AreEqual(1234, results.First().Total); msTransaction.Complete(); } Assert.IsFalse(client.InTransaction); } }
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 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); var ex = Assert.Throws<InvalidOperationException>(() => tran.Commit()); Assert.AreEqual("Cannot commit unless all tasks have been completed", ex.Message); } } }
public async Task 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, "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/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 = await testHarness.CreateAndConnectGraphClient(); //Act //Act var results = await graphClient.ExecuteGetCypherResultsAsync <ResultWithRelationshipDto>(cypherQuery); //Assert Assert.IsAssignableFrom <IEnumerable <ResultWithRelationshipDto> >(results); var resultsArray = results.ToArray(); Assert.Equal(3, resultsArray.Count()); var firstResult = resultsArray[0]; Assert.Equal(0, firstResult.Fooness.Reference.Id); Assert.Equal("bar", firstResult.Fooness.Data.Bar); Assert.Equal("baz", firstResult.Fooness.Data.Baz); Assert.Equal("HOSTS", firstResult.RelationshipType); Assert.Equal("foo", firstResult.Name); Assert.Equal(44321, firstResult.UniqueId); var secondResult = resultsArray[1]; Assert.Equal(1, secondResult.Fooness.Reference.Id); Assert.Equal("bar", secondResult.Fooness.Data.Bar); Assert.Equal("baz", secondResult.Fooness.Data.Baz); Assert.Equal("LIKES", secondResult.RelationshipType); Assert.Equal("bar", secondResult.Name); Assert.Equal(44311, secondResult.UniqueId); var thirdResult = resultsArray[2]; Assert.Equal(2, thirdResult.Fooness.Reference.Id); Assert.Equal("bar", thirdResult.Fooness.Data.Bar); Assert.Equal("baz", thirdResult.Fooness.Data.Baz); Assert.Equal("HOSTS", thirdResult.RelationshipType); Assert.Equal("baz", thirdResult.Name); Assert.Equal(42586, thirdResult.UniqueId); } }
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 async Task 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, "neo4j"); var cypherApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery) }; using (var testHarness = new RestTestHarness { { MockRequest.PostObjectAsJson("/transaction/commit", 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 = await testHarness.CreateAndConnectGraphClient(); //Act var results = await graphClient.ExecuteGetCypherResultsAsync <CollectResult>(cypherQuery); //Assert Assert.IsAssignableFrom <IEnumerable <CollectResult> >(results); var resultsArray = results.ToArray(); Assert.Equal(1, resultsArray.Count()); var firstResult = resultsArray[0]; Assert.Equal(358, firstResult.ColumnA.Reference.Id); Assert.Equal("BHP", firstResult.ColumnA.Data.Bar); Assert.Equal("1", firstResult.ColumnA.Data.Baz); var collectedResults = firstResult.ColumnBFromCollect.ToArray(); Assert.Equal(2, collectedResults.Count()); var firstCollectedResult = collectedResults[0]; Assert.Equal(362, firstCollectedResult.Reference.Id); Assert.Equal("Board", firstCollectedResult.Data.OpportunityType); Assert.Equal("Foo", firstCollectedResult.Data.Description); var secondCollectedResult = collectedResults[1]; Assert.Equal(359, secondCollectedResult.Reference.Id); Assert.Equal("Executive", secondCollectedResult.Data.OpportunityType); Assert.Equal("Bar", secondCollectedResult.Data.Description); } }
public void AsyncRequestsInTransactionShouldBeExecutedInOrder() { const string queryTextBase = @"MATCH (n) RETURN {0} as Total"; const string resultColumnBase = @"{{'columns':['Total'], 'data':[{{'row':[{0}]}}]}}"; const int asyncRequests = 15; var queries = new CypherQuery[asyncRequests]; var apiQueries = new CypherStatementList[asyncRequests]; var responses = new MockResponse[asyncRequests]; var testHarness = new RestHarnessWithCounter(); for (int i = 0; i < asyncRequests; i++) { queries[i] = new CypherQuery(string.Format(queryTextBase, i), new Dictionary <string, object>(), CypherResultMode.Projection); apiQueries[i] = new CypherStatementList { new CypherTransactionStatement(queries[i], false) }; responses[i] = MockResponse.Json(200, @"{'results':[" + string.Format(resultColumnBase, i) + @"], 'errors':[] }"); if (i > 0) { testHarness.Add(MockRequest.PostObjectAsJson("/transaction/1", apiQueries[i]), responses[i]); } } testHarness.Add( MockRequest.PostObjectAsJson("/transaction", apiQueries[0]), MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1, string.Format(resultColumnBase, 0)), "http://foo/db/data/transaction/1") ); testHarness.Add( MockRequest.PostJson("/transaction/1/commit", @"{'statements': []}"), MockResponse.Json(200, @"{'results':[], 'errors':[] }") ); try { var client = testHarness.CreateAndConnectTransactionalGraphClient(); var rawClient = (IRawGraphClient)client; var tasks = new Task[asyncRequests]; using (var tran = client.BeginTransaction()) { for (int i = 0; i < asyncRequests; i++) { int tmpResult = i; tasks[i] = rawClient.ExecuteGetCypherResultsAsync <DummyTotal>(queries[i]).ContinueWith(task => { Assert.AreEqual(tmpResult, task.Result.Single().Total); }); } Task.WaitAll(tasks); tran.Commit(); } } finally { testHarness.Dispose(); } // check that we have a total order Assert.AreEqual(asyncRequests, testHarness.Queue.Count); int lastElement = -1; for (int i = 0; i < asyncRequests; i++) { int headItem; Assert.IsTrue(testHarness.Queue.TryDequeue(out headItem)); Assert.Greater(headItem, lastElement); lastElement = headItem; } }