diff options
author | Esha Maharishi <esha.maharishi@mongodb.com> | 2019-04-29 15:54:20 -0400 |
---|---|---|
committer | Esha Maharishi <esha.maharishi@mongodb.com> | 2019-05-02 14:54:20 -0400 |
commit | 2d54db5b603d8ac3d4529f773614db36ab1298e6 (patch) | |
tree | ba012bb80543ae4352664f55e891317bbd949eda /src/mongo/db/transaction_participant_test.cpp | |
parent | e85431e9c1cecb8d6eafee706b46c30c1aaa24d3 (diff) | |
download | mongo-2d54db5b603d8ac3d4529f773614db36ab1298e6.tar.gz |
SERVER-40808 Recovering a transaction's outcome should block if the participant is in prepare
Diffstat (limited to 'src/mongo/db/transaction_participant_test.cpp')
-rw-r--r-- | src/mongo/db/transaction_participant_test.cpp | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/mongo/db/transaction_participant_test.cpp b/src/mongo/db/transaction_participant_test.cpp index 83eeba96415..00d04754702 100644 --- a/src/mongo/db/transaction_participant_test.cpp +++ b/src/mongo/db/transaction_participant_test.cpp @@ -3711,5 +3711,82 @@ TEST_F(TxnParticipantTest, OldestActiveTransactionTimestampTimeout) { ASSERT_TRUE(ErrorCodes::isInterruption(statusWith.getStatus().code())); }; +TEST_F(TxnParticipantTest, ExitPreparePromiseIsFulfilledOnAbortAfterPrepare) { + MongoDOperationContextSession opCtxSession(opCtx()); + auto txnParticipant = TransactionParticipant::get(opCtx()); + + txnParticipant.beginOrContinue( + opCtx(), *opCtx()->getTxnNumber(), false /* autocommit */, true /* startTransaction */); + ASSERT_TRUE(txnParticipant.onExitPrepare().isReady()); + + txnParticipant.unstashTransactionResources(opCtx(), "find"); + ASSERT_TRUE(txnParticipant.onExitPrepare().isReady()); + + const auto prepareOpTime = repl::OpTime({3, 2}, 0); + txnParticipant.prepareTransaction(opCtx(), prepareOpTime); + const auto exitPrepareFuture = txnParticipant.onExitPrepare(); + ASSERT_FALSE(exitPrepareFuture.isReady()); + + txnParticipant.abortActiveTransaction(opCtx()); + ASSERT_TRUE(exitPrepareFuture.isReady()); + + // Once the promise has been fulfilled, new callers of onExitPrepare should immediately be + // ready. + ASSERT_TRUE(txnParticipant.onExitPrepare().isReady()); + + // abortTransaction is retryable, but does not cause the completion promise to be set again. + txnParticipant.abortActiveTransaction(opCtx()); +} + +TEST_F(TxnParticipantTest, ExitPreparePromiseIsFulfilledOnCommitAfterPrepare) { + MongoDOperationContextSession opCtxSession(opCtx()); + auto txnParticipant = TransactionParticipant::get(opCtx()); + + txnParticipant.beginOrContinue( + opCtx(), *opCtx()->getTxnNumber(), false /* autocommit */, true /* startTransaction */); + ASSERT_TRUE(txnParticipant.onExitPrepare().isReady()); + + txnParticipant.unstashTransactionResources(opCtx(), "find"); + ASSERT_TRUE(txnParticipant.onExitPrepare().isReady()); + + const auto prepareOpTime = repl::OpTime({3, 2}, 0); + const auto prepareTimestamp = txnParticipant.prepareTransaction(opCtx(), prepareOpTime); + const auto exitPrepareFuture = txnParticipant.onExitPrepare(); + ASSERT_FALSE(exitPrepareFuture.isReady()); + + const auto commitTimestamp = + Timestamp(prepareTimestamp.getSecs(), prepareTimestamp.getInc() + 1); + txnParticipant.commitPreparedTransaction(opCtx(), commitTimestamp, {}); + ASSERT_TRUE(exitPrepareFuture.isReady()); + + // Once the promise has been fulfilled, new callers of onExitPrepare should immediately be + // ready. + ASSERT_TRUE(txnParticipant.onExitPrepare().isReady()); +} + +TEST_F(TxnParticipantTest, ExitPreparePromiseIsFulfilledOnAbortPreparedTransactionForRollback) { + MongoDOperationContextSession opCtxSession(opCtx()); + auto txnParticipant = TransactionParticipant::get(opCtx()); + + txnParticipant.beginOrContinue( + opCtx(), *opCtx()->getTxnNumber(), false /* autocommit */, true /* startTransaction */); + ASSERT_TRUE(txnParticipant.onExitPrepare().isReady()); + + txnParticipant.unstashTransactionResources(opCtx(), "find"); + ASSERT_TRUE(txnParticipant.onExitPrepare().isReady()); + + const auto prepareOpTime = repl::OpTime({3, 2}, 0); + txnParticipant.prepareTransaction(opCtx(), prepareOpTime); + const auto exitPrepareFuture = txnParticipant.onExitPrepare(); + ASSERT_FALSE(exitPrepareFuture.isReady()); + + txnParticipant.abortPreparedTransactionForRollback(opCtx()); + ASSERT_TRUE(exitPrepareFuture.isReady()); + + // Once the promise has been fulfilled, new callers of onExitPrepare should immediately be + // ready. + ASSERT_TRUE(txnParticipant.onExitPrepare().isReady()); +} + } // namespace } // namespace mongo |