@Test
  public void shouldSuspendTransactionAndReleaseForOtherRequestsAfterExecutingStatements()
      throws Exception {
    // given
    KernelAPI kernel = mockKernel();
    TransitionalTxManagementKernelTransaction transactionContext =
        (TransitionalTxManagementKernelTransaction) kernel.newTransaction();

    TransactionRegistry registry = mock(TransactionRegistry.class);
    when(registry.begin()).thenReturn(1337l);

    ExecutionEngine engine = mock(ExecutionEngine.class);
    ExecutionResult executionResult = mock(ExecutionResult.class);
    when(engine.execute("query", map())).thenReturn(executionResult);
    TransactionHandle handle =
        new TransactionHandle(kernel, engine, registry, uriScheme, StringLogger.DEV_NULL);
    ExecutionResultSerializer output = mock(ExecutionResultSerializer.class);

    // when
    handle.execute(
        statements(new Statement("query", map(), false, (ResultDataContent[]) null)), output);

    // then
    InOrder transactionOrder = inOrder(transactionContext, registry);
    transactionOrder.verify(transactionContext).suspendSinceTransactionsAreStillThreadBound();
    transactionOrder.verify(registry).release(1337l, handle);

    InOrder outputOrder = inOrder(output);
    outputOrder.verify(output).transactionCommitUri(uriScheme.txCommitUri(1337));
    outputOrder.verify(output).statementResult(executionResult, false, (ResultDataContent[]) null);
    outputOrder.verify(output).transactionStatus(anyLong());
    outputOrder.verify(output).errors(argThat(hasNoErrors()));
    outputOrder.verify(output).finish();
    verifyNoMoreInteractions(output);
  }
  @Test
  public void shouldRollbackTransactionIfExecutionErrorOccurs() throws Exception {
    // given
    KernelAPI kernel = mockKernel();
    TransitionalTxManagementKernelTransaction transactionContext =
        (TransitionalTxManagementKernelTransaction) kernel.newTransaction();

    TransactionRegistry registry = mock(TransactionRegistry.class);
    when(registry.begin()).thenReturn(1337l);

    ExecutionEngine executionEngine = mock(ExecutionEngine.class);
    when(executionEngine.execute("query", map())).thenThrow(new NullPointerException());

    TransactionHandle handle =
        new TransactionHandle(kernel, executionEngine, registry, uriScheme, StringLogger.DEV_NULL);
    ExecutionResultSerializer output = mock(ExecutionResultSerializer.class);

    // when
    handle.execute(
        statements(new Statement("query", map(), false, (ResultDataContent[]) null)), output);

    // then
    verify(transactionContext).rollback();
    verify(registry).forget(1337l);

    InOrder outputOrder = inOrder(output);
    outputOrder.verify(output).transactionCommitUri(uriScheme.txCommitUri(1337));
    outputOrder
        .verify(output)
        .errors(argThat(hasErrors(StatusCode.INTERNAL_STATEMENT_EXECUTION_ERROR)));
    outputOrder.verify(output).finish();
    verifyNoMoreInteractions(output);
  }
  @Test
  public void shouldExecuteStatements() throws Exception {
    // given
    KernelAPI kernel = mockKernel();

    ExecutionEngine executionEngine = mock(ExecutionEngine.class);
    ExecutionResult executionResult = mock(ExecutionResult.class);
    when(executionEngine.execute("query", map())).thenReturn(executionResult);
    TransactionRegistry registry = mock(TransactionRegistry.class);
    when(registry.begin()).thenReturn(1337l);
    TransactionHandle handle =
        new TransactionHandle(kernel, executionEngine, registry, uriScheme, StringLogger.DEV_NULL);
    ExecutionResultSerializer output = mock(ExecutionResultSerializer.class);

    // when
    handle.execute(
        statements(new Statement("query", map(), false, (ResultDataContent[]) null)), output);

    // then
    verify(executionEngine).execute("query", map());

    InOrder outputOrder = inOrder(output);
    outputOrder.verify(output).transactionCommitUri(uriScheme.txCommitUri(1337));
    outputOrder.verify(output).statementResult(executionResult, false, (ResultDataContent[]) null);
    outputOrder.verify(output).transactionStatus(anyLong());
    outputOrder.verify(output).errors(argThat(hasNoErrors()));
    outputOrder.verify(output).finish();
    verifyNoMoreInteractions(output);
  }
  @Test
  public void shouldRollbackTransactionIfDeserializationErrorOccurs() throws Exception {
    // given
    KernelAPI kernel = mockKernel();
    TransitionalTxManagementKernelTransaction transactionContext =
        (TransitionalTxManagementKernelTransaction) kernel.newTransaction();

    TransactionRegistry registry = mock(TransactionRegistry.class);
    when(registry.begin()).thenReturn(1337l);

    TransactionHandle handle =
        new TransactionHandle(
            kernel, mock(ExecutionEngine.class), registry, uriScheme, StringLogger.DEV_NULL);
    ExecutionResultSerializer output = mock(ExecutionResultSerializer.class);

    // when
    handle.execute(
        deserilizationErrors(new Neo4jError(StatusCode.INVALID_REQUEST_FORMAT, new Exception())),
        output);

    // then
    verify(transactionContext).rollback();
    verify(registry).forget(1337l);

    InOrder outputOrder = inOrder(output);
    outputOrder.verify(output).transactionCommitUri(uriScheme.txCommitUri(1337));
    outputOrder.verify(output).errors(argThat(hasErrors(StatusCode.INVALID_REQUEST_FORMAT)));
    outputOrder.verify(output).finish();
    verifyNoMoreInteractions(output);
  }