public async Task BatchDmlAbortsTwice()
            {
                var spannerClientMock = SpannerClientHelpers
                                        .CreateMockClient(Logger.DefaultLogger, MockBehavior.Strict)
                                        .SetupBatchCreateSessionsAsync()
                                        .SetupBeginTransactionAsync()
                                        .SetupExecuteBatchDmlAsync_Fails(failures: 2, statusCode: StatusCode.Aborted)
                                        .SetupCommitAsync()
                                        .SetupRollbackAsync();

                SpannerConnection connection = BuildSpannerConnection(spannerClientMock);

                var scheduler = (FakeScheduler)connection.Builder.SessionPoolManager.SpannerSettings.Scheduler;
                var time0     = scheduler.Clock.GetCurrentDateTimeUtc();
                var callee    = new Callee(scheduler);

                await scheduler.RunAsync(async() =>
                {
                    var result = await connection.RunWithRetriableTransactionAsync(transaction => callee.DatabaseWorkAsync(connection, transaction));
                    Assert.Equal(3, result);
                });

                callee.AssertBackoffTimesInRange(time0);
                callee.AssertLastCallTime(scheduler.Clock.GetCurrentDateTimeUtc());
            }
            public async Task CommitFailsOtherThanAborted()
            {
                var spannerClientMock = SpannerClientHelpers
                                        .CreateMockClient(Logger.DefaultLogger, MockBehavior.Strict)
                                        .SetupBatchCreateSessionsAsync()
                                        .SetupBeginTransactionAsync()
                                        .SetupExecuteBatchDmlAsync()
                                        .SetupCommitAsync_Fails(failures: 1, StatusCode.Unknown)
                                        .SetupRollbackAsync();

                SpannerConnection connection = BuildSpannerConnection(spannerClientMock);

                var scheduler = (FakeScheduler)connection.Builder.SessionPoolManager.SpannerSettings.Scheduler;
                var time0     = scheduler.Clock.GetCurrentDateTimeUtc();
                var callee    = new Callee(scheduler);

                await scheduler.RunAsync(async() =>
                {
                    var exception = await Assert.ThrowsAsync <SpannerException>(
                        () => connection.RunWithRetriableTransactionAsync(
                            transaction => callee.DatabaseWorkAsync(connection, transaction)));
                    Assert.Contains("Bang!", exception.InnerException.Message);
                });

                callee.AssertBackoffTimesInRange(time0);
                callee.AssertLastCallTime(scheduler.Clock.GetCurrentDateTimeUtc());
            }
            public async Task WorkFails()
            {
                var spannerClientMock = SpannerClientHelpers
                                        .CreateMockClient(Logger.DefaultLogger, MockBehavior.Strict)
                                        .SetupBatchCreateSessionsAsync()
                                        .SetupBeginTransactionAsync()
                                        .SetupRollbackAsync();

                SpannerConnection connection = BuildSpannerConnection(spannerClientMock);

                var scheduler = (FakeScheduler)connection.Builder.SessionPoolManager.SpannerSettings.Scheduler;
                var time0     = scheduler.Clock.GetCurrentDateTimeUtc();
                var callee    = new Callee(scheduler);

                await scheduler.RunAsync(async() =>
                {
                    var exception = await Assert.ThrowsAsync <InvalidOperationException>(() => connection.RunWithRetriableTransactionAsync(callee.Fails));
                    Assert.Contains("Bang!", exception.Message);
                });

                callee.AssertBackoffTimesInRange(time0);
                callee.AssertLastCallTime(scheduler.Clock.GetCurrentDateTimeUtc());
            }