summaryrefslogtreecommitdiff
path: root/src/mongo/db/repl/rs_rollback_test.cpp
diff options
context:
space:
mode:
authorJack Mulrow <jack.mulrow@mongodb.com>2017-06-26 17:30:16 -0400
committerJack Mulrow <jack.mulrow@mongodb.com>2017-07-12 15:32:49 -0400
commit32ce928cb3275bb3de7c1e1ccc99d3c1e57cdc72 (patch)
treefdf47bdbf89faec183b05ab48b3a898923b94bf6 /src/mongo/db/repl/rs_rollback_test.cpp
parent4b9d69eb00361083ce835d42c4107a4caa52f6fc (diff)
downloadmongo-32ce928cb3275bb3de7c1e1ccc99d3c1e57cdc72.tar.gz
SERVER-29531 Handle rollbacks in SessionTransactionTable
Diffstat (limited to 'src/mongo/db/repl/rs_rollback_test.cpp')
-rw-r--r--src/mongo/db/repl/rs_rollback_test.cpp87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/mongo/db/repl/rs_rollback_test.cpp b/src/mongo/db/repl/rs_rollback_test.cpp
index 3d2bd032c64..b36dbb08789 100644
--- a/src/mongo/db/repl/rs_rollback_test.cpp
+++ b/src/mongo/db/repl/rs_rollback_test.cpp
@@ -1396,6 +1396,93 @@ TEST(RSRollbackTest, LocalEntryWithoutO2IsFatal) {
RSFatalException);
}
+DEATH_TEST_F(RSRollbackTest, LocalEntryWithTxnNumberWithoutSessionIdIsFatal, "invariant") {
+ auto validOplogEntry = BSON("ts" << Timestamp(Seconds(1), 0) << "t" << 1LL << "h" << 1LL << "op"
+ << "i"
+ << "ui"
+ << UUID::gen()
+ << "ns"
+ << "test.t"
+ << "o"
+ << BSON("_id" << 1 << "a" << 1));
+ FixUpInfo fui;
+ ASSERT_OK(updateFixUpInfoFromLocalOplogEntry(fui, validOplogEntry));
+
+ const auto txnNumber = BSON("txnNumber" << 1LL);
+ const auto noSessionIdOrStmtId = validOplogEntry.addField(txnNumber.firstElement());
+
+ const auto stmtId = BSON("stmtId" << 1);
+ const auto noSessionId = noSessionIdOrStmtId.addField(stmtId.firstElement());
+ ASSERT_THROWS(updateFixUpInfoFromLocalOplogEntry(fui, noSessionId).transitional_ignore(),
+ RSFatalException);
+}
+
+DEATH_TEST_F(RSRollbackTest, LocalEntryWithTxnNumberWithoutStmtIdIsFatal, "invariant") {
+ auto validOplogEntry = BSON("ts" << Timestamp(Seconds(1), 0) << "t" << 1LL << "h" << 1LL << "op"
+ << "i"
+ << "ui"
+ << UUID::gen()
+ << "ns"
+ << "test.t"
+ << "o"
+ << BSON("_id" << 1 << "a" << 1));
+ FixUpInfo fui;
+ ASSERT_OK(updateFixUpInfoFromLocalOplogEntry(fui, validOplogEntry));
+
+ const auto txnNumber = BSON("txnNumber" << 1LL);
+ const auto noSessionIdOrStmtId = validOplogEntry.addField(txnNumber.firstElement());
+
+ const auto uuid = UUID::gen();
+ const auto sessionId = BSON("lsid" << BSON("id" << uuid.toBSON()));
+ const auto noStmtId = noSessionIdOrStmtId.addField(sessionId.firstElement());
+ ASSERT_THROWS(updateFixUpInfoFromLocalOplogEntry(fui, noStmtId).transitional_ignore(),
+ RSFatalException);
+}
+
+TEST(RSRollbackTest, LocalEntryWithTxnNumberAddsTransactionTableDocToBeRefetched) {
+ FixUpInfo fui;
+ auto entryWithoutTxnNumber =
+ BSON("ts" << Timestamp(Seconds(1), 0) << "t" << 1LL << "h" << 1LL << "op"
+ << "i"
+ << "ui"
+ << UUID::gen()
+ << "ns"
+ << "test.t2"
+ << "o"
+ << BSON("_id" << 2 << "a" << 2));
+ ASSERT_OK(updateFixUpInfoFromLocalOplogEntry(fui, entryWithoutTxnNumber));
+
+ // With no txnNumber present, no extra documents need to be refetched.
+ ASSERT_EQ(fui.docsToRefetch.size(), 1U);
+
+ auto entryWithTxnNumber =
+ BSON("ts" << Timestamp(Seconds(1), 0) << "t" << 1LL << "h" << 1LL << "op"
+ << "i"
+ << "ui"
+ << UUID::gen()
+ << "ns"
+ << "test.t"
+ << "o"
+ << BSON("_id" << 1 << "a" << 1)
+ << "txnNumber"
+ << 1LL
+ << "stmtId"
+ << 1
+ << "lsid"
+ << BSON("id" << UUID::gen().toBSON()));
+ ASSERT_OK(updateFixUpInfoFromLocalOplogEntry(fui, entryWithTxnNumber));
+
+ // If txnNumber is present, the session transactions table document corresponding to the oplog
+ // entry's sessionId also needs to be refetched.
+ ASSERT_EQ(fui.docsToRefetch.size(), 3U);
+
+ DocID expectedTxnDoc;
+ expectedTxnDoc.ownedObj = BSON("_id" << entryWithTxnNumber["lsid"]);
+ expectedTxnDoc._id = expectedTxnDoc.ownedObj.firstElement();
+ expectedTxnDoc.ns = NamespaceString::kSessionTransactionsTableNamespace.ns().c_str();
+ ASSERT_TRUE(fui.docsToRefetch.find(expectedTxnDoc) != fui.docsToRefetch.end());
+}
+
TEST_F(RSRollbackTest, RollbackReturnsImmediatelyOnFailureToTransitionToRollback) {
// On failing to transition to ROLLBACK, rollback() should return immediately and not call
// syncRollback(). We provide an empty oplog so that if syncRollback() is called erroneously,