public void CurrentInternalTransaction_ReturnsNullWhenEmpty() { using (var testHarness = new RestTestHarness()) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); client.Connect(); var tm = new Neo4jClient.Transactions.TransactionManager(client) { ScopedTransactions = new Stack<TransactionScopeProxy>() }; Assert.AreEqual(0, tm.ScopedTransactions.Count); Assert.IsNull(tm.CurrentInternalTransaction); } }
public void CannotJoinAfterClosedTransaction() { using (var testHarness = new RestTestHarness()) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var tran = client.BeginTransaction()) { tran.Commit(); Assert.IsFalse(tran.IsOpen); // should fail here Assert.That(() => client.BeginTransaction(), Throws.TypeOf<ClosedTransactionException>()); } } }
public void CannotJoinAfterClosedTransaction() { using (var testHarness = new RestTestHarness()) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var tran = client.BeginTransaction()) { tran.Commit(); Assert.IsFalse(tran.IsOpen); // should fail here using (var tran2 = client.BeginTransaction()) { } } } }
public void CommitInRequiresNewDoesntAffectParentScope() { using (var testHarness = new RestTestHarness()) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var tran = client.BeginTransaction()) { using (var tran2 = client.BeginTransaction(TransactionScopeOption.RequiresNew)) { tran2.Commit(); Assert.IsFalse(tran2.IsOpen); } Assert.IsTrue(tran.IsOpen); } Assert.IsFalse(client.InTransaction); } }
private void ExecuteRestMethodUnderTransaction( Action<IGraphClient> restAction, TransactionScopeOption option = TransactionScopeOption.Join, IEnumerable<KeyValuePair<MockRequest, MockResponse>> requests = null) { requests = requests ?? Enumerable.Empty<KeyValuePair<MockRequest, MockResponse>>(); using (var testHarness = new RestTestHarness()) { foreach (var request in requests) { testHarness.Add(request.Key, request.Value); } var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var transaction = client.BeginTransaction(option)) { restAction(client); } } }
public void CommitWithoutRequestsShouldNotGenerateMessage() { var initTransactionRequest = MockRequest.PostJson("/transaction", @"{'statements': []}"); var commitTransactionRequest = MockRequest.PostJson("/transaction/1/commit", @"{'statements': []}"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { commitTransactionRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }.ShouldNotBeCalled(initTransactionRequest, commitTransactionRequest)) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var transaction = client.BeginTransaction()) { // no requests transaction.Commit(); } } }
public void CommitWithoutRequestsShouldNotGenerateMessage() { var initTransactionRequest = MockRequest.PostJson("/transaction", @"{'statements': []}"); var commitTransactionRequest = MockRequest.PostJson("/transaction/1/commit", @"{'statements': []}"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { commitTransactionRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }.ShouldNotBeCalled(initTransactionRequest, commitTransactionRequest)) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var transaction = client.BeginTransaction()) { // no requests transaction.Commit(); } } }
public void JoinTransactionAfterSuppressCreatesNewTransaction() { using (var testHarness = new RestTestHarness()) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var tran = client.BeginTransaction()) { using (var tran2 = client.BeginTransaction(TransactionScopeOption.Suppress)) { Assert.AreNotSame(tran2, tran); Assert.IsFalse(client.InTransaction); using (var tran3 = client.BeginTransaction(TransactionScopeOption.Join)) { Assert.AreNotSame(GetRealTransaction(tran2), GetRealTransaction(tran3)); Assert.AreNotSame(GetRealTransaction(tran3), GetRealTransaction(tran2)); Assert.IsTrue(client.InTransaction); } } Assert.IsTrue(client.InTransaction); } Assert.IsFalse(client.InTransaction); } }
public async Task ThrowsClosedTransactionException_WhenTransactionAlreadyClosed() { const string database = "neo4jclient"; var initTransactionRequest = MockRequest.PostJson($"/db/{database}/tx", "{'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var rollbackTransactionRequest = MockRequest.Delete($"/db/{database}/tx/1"); var commitTransactionRequest = MockRequest.PostJson($"/db/{database}/tx/1/commit", EmptyStatements); using (var testHarness = new RestTestHarness(false, "http://foo:7474") { { initTransactionRequest, MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1), $"http://foo:7474/db/{database}/tx/1") }, { commitTransactionRequest, EmptyOkResponse }, { rollbackTransactionRequest, EmptyOkResponse } }) { var client = await testHarness.CreateAndConnectTransactionalGraphClient(RestTestHarness.Neo4jVersion.Neo40); using (var transaction = client.BeginTransaction(TransactionScopeOption.Join, null, database)) { // dummy query to generate request await client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResultsAsync().ConfigureAwait(false); await transaction.CommitAsync().ConfigureAwait(false); var ex = await Assert.ThrowsAsync <ClosedTransactionException>(async() => await transaction.RollbackAsync()); ex.Should().NotBeNull(); } } }
public async Task ShouldPromoteBadQueryResponseToNiceException() { // Arrange const string queryText = @"broken query"; var cypherQuery = new CypherQuery(queryText, new Dictionary <string, object>(), CypherResultMode.Projection, "neo4j"); var cypherApiQuery = new CypherStatementList { new CypherTransactionStatement(cypherQuery) }; 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 = await testHarness.CreateAndConnectTransactionalGraphClient(); var rawClient = (IRawGraphClient)graphClient; using (graphClient.BeginTransaction()) { var ex = await Assert.ThrowsAsync <NeoException>(async() => await rawClient.ExecuteCypherAsync(cypherQuery)); Assert.Equal("InvalidSyntax: Invalid input b: expected SingleStatement (line 1, column 1)\nThis is not a valid Cypher Statement.\n ^", ex.Message); Assert.Equal("Invalid input b: expected SingleStatement (line 1, column 1)\nThis is not a valid Cypher Statement.\n ^", ex.NeoMessage); Assert.Equal("InvalidSyntax", ex.NeoExceptionName); Assert.Equal("Neo.ClientError.Statement.InvalidSyntax", ex.NeoFullName); Assert.Equal(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, 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 TwoThreadsShouldNotHaveTheSameTransactionObject() { // if thread support is not well implemented then the t2's BeginTransaction will fail with NotSupportedException ITransaction transactionFromThread1 = null; ITransaction transactionFromThread2 = null; using (var testHarness = new RestTestHarness()) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); var firstTransactionSet = new EventWaitHandle(false, EventResetMode.AutoReset); var secondTransactionSet = new EventWaitHandle(false, EventResetMode.AutoReset); var t1 = new Task(() => { try { using (var transaction = client.BeginTransaction()) { transactionFromThread1 = transaction; firstTransactionSet.Set(); secondTransactionSet.WaitOne(); } } catch (Exception e) { firstTransactionSet.Set(); throw; } }); var t2 = new Task(() => { firstTransactionSet.WaitOne(); try { using (var transaction = client.BeginTransaction()) { transactionFromThread2 = transaction; secondTransactionSet.Set(); } } catch (Exception e) { secondTransactionSet.Set(); throw; } }); t1.Start(); t2.Start(); Task.WaitAll(t1, t2); Assert.IsNotNull(transactionFromThread1); Assert.IsNotNull(transactionFromThread2); Assert.AreNotEqual(transactionFromThread1, transactionFromThread2); } }
public void DeserializeResultsFromTransaction() { var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var deserializationRequest = MockRequest.PostJson("/transaction/1", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var rollbackTransactionRequest = MockRequest.Delete("/transaction/1"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { deserializationRequest, MockResponse.Json(200, @"{'results':[{'columns': ['count(n)'], 'data': [{'row': [0]}]}]}") }, { rollbackTransactionRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var transaction = client.BeginTransaction()) { // dummy query to generate request client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResults(); // this query will hit the deserializer var count = client.Cypher .Match("n") .Return(n => n.Count()) .Results; Assert.AreEqual(count.First(), 0); } } }
public void TransactionCommit() { var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var commitRequest = MockRequest.PostJson("/transaction/1/commit", @"{'statements': []}"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { commitRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var transaction = client.BeginTransaction()) { // dummy query to generate request client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResults(); transaction.Commit(); } } }
public void UpdateTransactionEndpointAfterFirstRequest() { var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var rollbackTransactionRequest = MockRequest.Delete("/transaction/1"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { rollbackTransactionRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var transaction = client.BeginTransaction()) { // dummy query to generate request client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResults(); Assert.AreEqual( new Uri("http://foo/db/data/transaction/1"), ((INeo4jTransaction)((TransactionScopeProxy) transaction).TransactionContext).Endpoint); } } }
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 SuppressTransactionScopeShouldNotEmitTransactionalQuery() { var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var nonTransactionalRequest = MockRequest.PostJson("/cypher", @"{'query': 'MATCH n\r\nRETURN count(n)', 'params': {}}"); var commitTransactionRequest = MockRequest.PostJson("/transaction/1/commit", @"{ 'statements': []}"); var deleteRequest = MockRequest.Delete("/transaction/1"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { commitTransactionRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") }, { nonTransactionalRequest, MockResponse.Json(200, @"{'columns':['count(n)'], 'data':[[0]] }") }, { deleteRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }.ShouldNotBeCalled(deleteRequest)) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var tran = new TransactionScope()) { using (var tran2 = new TransactionScope(TransactionScopeOption.Suppress)) { client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResults(); // no rollback should be generated } client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResults(); tran.Complete(); } } }
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, TransactionRestResponseHelper.GenerateInitTransactionResponse(1, resultColumn), "http://foo/db/data/transaction/1") }, { MockRequest.PostObjectAsJson("/transaction", cypherQueryTxStatement), MockResponse.Json(201, TransactionRestResponseHelper.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 RequiresNewCreateNewTransaction() { using (var testHarness = new RestTestHarness()) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var transaction = client.BeginTransaction()) { using (var tran2 = client.BeginTransaction(TransactionScopeOption.RequiresNew)) { Assert.AreNotSame(GetRealTransaction(tran2), GetRealTransaction(transaction)); Assert.IsTrue(client.InTransaction); } Assert.IsTrue(client.InTransaction); } Assert.IsFalse(client.InTransaction); } }
public void ExecuteMultipleStatementInOneRequestHttpRequest() { const string headerName = "MyTestHeader"; const string headerValue = "myTestHeaderValue"; var customHeaders = new NameValueCollection { { headerName, headerValue } }; var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}, {'statement': 'MATCH t\r\nRETURN count(t)', 'resultDataContents':[], 'parameters': {}}]}"); var commitRequest = MockRequest.PostJson("/transaction/1/commit", @"{'statements': []}"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { commitRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }) { var response = MockResponse.NeoRoot20(); testHarness.Add(MockRequest.Get(""), response); var httpClient = testHarness.GenerateHttpClient("http://foo/db/data"); testHarness.CreateAndConnectTransactionalGraphClient(); ITransactionalGraphClient client = new GraphClient(new Uri("http://foo/db/data"), httpClient); client.Connect(); using (var transaction = client.BeginTransaction()) { // dummy query to generate request var rawClient = client as IRawGraphClient; if (rawClient == null) { Assert.Fail("ITransactionalGraphClient is not IRawGraphClient"); } var queries = new List <CypherQuery>() { client.Cypher .Match("n") .Return(n => n.Count()) .Query, client.Cypher .Match("t") .Return(t => t.Count()) .Query }; httpClient.ClearReceivedCalls(); rawClient.ExecuteMultipleCypherQueriesInTransaction(queries, customHeaders); transaction.Commit(); var calls = httpClient.ReceivedCalls().ToList(); Assert.IsNotEmpty(calls); HttpRequestMessage requestMessage = null; foreach (var call in calls) { if (call.GetArguments().Single().GetType() == typeof(HttpRequestMessage)) { requestMessage = (HttpRequestMessage)call.GetArguments().Single(); } } Assert.IsNotNull(requestMessage); var customHeader = requestMessage.Headers.Single(h => h.Key == headerName); Assert.IsNotNull(customHeader); Assert.AreEqual(headerValue, customHeader.Value.Single()); } } }
public void JoinedTransactionsCommitAfterAllEmitVote() { using (var testHarness = new RestTestHarness()) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var tran = client.BeginTransaction()) { using (var tran2 = client.BeginTransaction()) { tran2.Commit(); } Assert.IsTrue(tran.IsOpen); using (var tran3 = client.BeginTransaction(TransactionScopeOption.Suppress)) { Assert.AreNotSame(GetRealTransaction(tran3), GetRealTransaction(tran)); Assert.IsFalse(client.InTransaction); } Assert.IsTrue(client.InTransaction); Assert.IsTrue(tran.IsOpen); tran.Commit(); Assert.IsFalse(tran.IsOpen); } Assert.IsFalse(client.InTransaction); } }
public void RollbackInJoinedTransactionClosesAllJoinedScopes() { using (var testHarness = new RestTestHarness()) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var tran = client.BeginTransaction()) { using (var tran2 = client.BeginTransaction()) { tran2.Rollback(); } Assert.IsFalse(tran.IsOpen); } Assert.IsFalse(client.InTransaction); } }
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 ExecuteMultipleStatementInOneRequest() { var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}, {'statement': 'MATCH t\r\nRETURN count(t)', 'resultDataContents':[], 'parameters': {}}]}"); var commitRequest = MockRequest.PostJson("/transaction/1/commit", @"{'statements': []}"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { commitRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var transaction = client.BeginTransaction()) { // dummy query to generate request var rawClient = client as IRawGraphClient; if (rawClient == null) { Assert.Fail("ITransactionalGraphClient is not IRawGraphClient"); } var queries = new List<CypherQuery>() { client.Cypher .Match("n") .Return(n => n.Count()) .Query, client.Cypher .Match("t") .Return(t => t.Count()) .Query }; rawClient.ExecuteMultipleCypherQueriesInTransaction(queries); transaction.Commit(); } } }
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 NestedJoinedTransactionScope() { var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var secondRequest = MockRequest.PostJson("/transaction/1", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var deleteRequest = MockRequest.Delete("/transaction/1"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { secondRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") }, { deleteRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var scope = new TransactionScope()) { using (var scope2 = new TransactionScope()) { client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResults(); // this will not commit scope2.Complete(); } // this should generate a request to the known transaction ID client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResults(); } } }
public void ExecuteMultipleStatementInOneRequestHttpRequest() { const string headerName = "MyTestHeader"; const string headerValue = "myTestHeaderValue"; var customHeaders = new NameValueCollection { {headerName, headerValue} }; var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}, {'statement': 'MATCH t\r\nRETURN count(t)', 'resultDataContents':[], 'parameters': {}}]}"); var commitRequest = MockRequest.PostJson("/transaction/1/commit", @"{'statements': []}"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, TransactionRestResponseHelper.GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { commitRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }) { var response = MockResponse.NeoRoot20(); testHarness.Add(MockRequest.Get(""), response); var httpClient = testHarness.GenerateHttpClient("http://foo/db/data"); testHarness.CreateAndConnectTransactionalGraphClient(); ITransactionalGraphClient client = new GraphClient(new Uri("http://foo/db/data"), httpClient); client.Connect(); using (var transaction = client.BeginTransaction()) { // dummy query to generate request var rawClient = client as IRawGraphClient; if (rawClient == null) { Assert.Fail("ITransactionalGraphClient is not IRawGraphClient"); } var queries = new List<CypherQuery>() { client.Cypher .Match("n") .Return(n => n.Count()) .Query, client.Cypher .Match("t") .Return(t => t.Count()) .Query }; httpClient.ClearReceivedCalls(); rawClient.ExecuteMultipleCypherQueriesInTransaction(queries, customHeaders); transaction.Commit(); var calls = httpClient.ReceivedCalls().ToList(); Assert.IsNotEmpty(calls); HttpRequestMessage requestMessage = null; foreach (var call in calls) { if (call.GetArguments().Single().GetType() == typeof (HttpRequestMessage)) { requestMessage = (HttpRequestMessage) call.GetArguments().Single(); } } Assert.IsNotNull(requestMessage); var customHeader = requestMessage.Headers.Single(h => h.Key == headerName); Assert.IsNotNull(customHeader); Assert.AreEqual(headerValue, customHeader.Value.Single()); } } }
public void PromoteDurableInAmbientTransaction() { // when two durables are registered they get promoted // this request will be made by the ForceKeepAlive() call when PSPE registration fails for the second client var afterPspeFailRequest = MockRequest.PostJson("/transaction", @"{'statements': []}"); // this request will be mode in Promote() after second durable enlistment var promoteRequest = MockRequest.PostJson("/transaction/1", @"{'statements': []}"); var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var secondClientRequest = MockRequest.PostJson("/transaction/2", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); // there are no delete requests because those will be made in another app domain using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { secondClientRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") }, { afterPspeFailRequest, MockResponse.Json(201, GenerateInitTransactionResponse(2), "http://foo/db/data/transaction/2") }, { promoteRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }) { using (var scope = new TransactionScope()) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResults(); var client2 = testHarness.CreateAndConnectTransactionalGraphClient(); client2.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResults(); } // we sleep so that the app domain for the resource manager gets cleaned up Thread.Sleep(500); } }
public void TransactionJoinedShouldBeTheSame() { using (var testHarness = new RestTestHarness()) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var transaction = client.BeginTransaction()) { using (var tran2 = client.BeginTransaction()) { Assert.AreSame(GetRealTransaction(tran2), GetRealTransaction(transaction)); } } } }
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 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 TransactionRollbackInTransactionScope() { var initTransactionRequest = MockRequest.PostJson("/transaction", @"{ 'statements': [{'statement': 'MATCH n\r\nRETURN count(n)', 'resultDataContents':[], 'parameters': {}}]}"); var deleteRequest = MockRequest.Delete("/transaction/1"); using (var testHarness = new RestTestHarness { { initTransactionRequest, MockResponse.Json(201, GenerateInitTransactionResponse(1), "http://foo/db/data/transaction/1") }, { deleteRequest, MockResponse.Json(200, @"{'results':[], 'errors':[] }") } }) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var scope = new TransactionScope()) { client.Cypher .Match("n") .Return(n => n.Count()) .ExecuteWithoutResults(); } } }
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 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 void FailsForRollbackInSuppressMode() { using (var testHarness = new RestTestHarness()) { var client = testHarness.CreateAndConnectTransactionalGraphClient(); using (var tran = client.BeginTransaction(TransactionScopeOption.Suppress)) { tran.Rollback(); } } }