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 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, "neo4j"); apiQueries[i] = new CypherStatementList { new CypherTransactionStatement(queries[i]) }; 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 = await 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.Equal(tmpResult, task.Result.Single().Total); }); } await Task.WhenAll(tasks); await tran.CommitAsync(); } } finally { testHarness.Dispose(); } // check that we have a total order Assert.Equal(asyncRequests, testHarness.Queue.Count); int lastElement = -1; for (int i = 0; i < asyncRequests; i++) { int headItem; Assert.True(testHarness.Queue.TryDequeue(out headItem)); headItem.Should().BeGreaterThan(lastElement); lastElement = headItem; } }