summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShin Yee Tan <shinyee.tan@mongodb.com>2022-12-21 15:09:50 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-12-21 15:39:20 +0000
commit3b467e88d14c42e789b62d1edb2ab06aec765f4f (patch)
tree57214ea3b9cb9ab7b4c05a325bdd948ab53588c5
parent82c46f01769d6cbae70a27ff948b0d93c49f7420 (diff)
downloadmongo-3b467e88d14c42e789b62d1edb2ab06aec765f4f.tar.gz
SERVER-71190 Create unittest for batched write context
-rw-r--r--src/mongo/db/op_observer/SConscript1
-rw-r--r--src/mongo/db/op_observer/batched_write_context_test.cpp194
-rw-r--r--src/mongo/db/op_observer/op_observer_impl_test.cpp57
3 files changed, 195 insertions, 57 deletions
diff --git a/src/mongo/db/op_observer/SConscript b/src/mongo/db/op_observer/SConscript
index 30af3ef369b..0cc24202ca6 100644
--- a/src/mongo/db/op_observer/SConscript
+++ b/src/mongo/db/op_observer/SConscript
@@ -128,6 +128,7 @@ env.Library(
env.CppUnitTest(
target='db_op_observer_test',
source=[
+ 'batched_write_context_test.cpp',
'batched_write_policy_test.cpp',
'op_observer_impl_test.cpp',
'op_observer_registry_test.cpp',
diff --git a/src/mongo/db/op_observer/batched_write_context_test.cpp b/src/mongo/db/op_observer/batched_write_context_test.cpp
new file mode 100644
index 00000000000..dc29da44e7e
--- /dev/null
+++ b/src/mongo/db/op_observer/batched_write_context_test.cpp
@@ -0,0 +1,194 @@
+/**
+ * Copyright (C) 2022-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#include "mongo/db/namespace_string.h"
+#include "mongo/db/op_observer/batched_write_context.h"
+#include "mongo/db/repl/oplog_entry.h"
+#include "mongo/db/service_context_test_fixture.h"
+#include "mongo/db/storage/write_unit_of_work.h"
+#include "mongo/unittest/death_test.h"
+#include "mongo/unittest/unittest.h"
+
+namespace mongo {
+
+namespace {
+
+// This test fixture provides access to a properly initialized global service context to test the
+// BatchedWriteContext class and its interaction with WriteUnitOfWork. For batched write
+// interactions with the oplog, see BatchedWriteOutputsTest.
+class BatchedWriteContextTest : public ServiceContextTest {};
+
+TEST_F(BatchedWriteContextTest, TestBatchingCondition) {
+ auto opCtxRaii = makeOperationContext();
+ auto opCtx = opCtxRaii.get();
+
+ auto& bwc = BatchedWriteContext::get(opCtx);
+ ASSERT(!bwc.writesAreBatched());
+ bwc.setWritesAreBatched(true);
+ ASSERT(bwc.writesAreBatched());
+ bwc.setWritesAreBatched(false);
+ ASSERT(!bwc.writesAreBatched());
+}
+
+DEATH_TEST_REGEX_F(BatchedWriteContextTest,
+ TestDoesNotSupportAddingBatchedOperationWhileWritesAreNotBatched,
+ "Invariant failure.*_batchWrites") {
+ auto opCtxRaii = makeOperationContext();
+ auto opCtx = opCtxRaii.get();
+
+ WriteUnitOfWork wuow(opCtx, /*groupOplogEntries=*/true);
+ auto& bwc = BatchedWriteContext::get(opCtx);
+ ASSERT(!bwc.writesAreBatched());
+
+ const NamespaceString nss{boost::none, "test", "coll"};
+ auto op = repl::MutableOplogEntry::makeDeleteOperation(nss, UUID::gen(), BSON("_id" << 0));
+ bwc.addBatchedOperation(opCtx, op);
+}
+
+DEATH_TEST_REGEX_F(BatchedWriteContextTest,
+ TestDoesNotSupportAddingBatchedOperationOutsideOfWUOW,
+ "Invariant failure.*inAWriteUnitOfWork()") {
+ auto opCtxRaii = makeOperationContext();
+ auto opCtx = opCtxRaii.get();
+
+ auto& bwc = BatchedWriteContext::get(opCtx);
+ // Need to explicitly set writes are batched to simulate op observer starting batched write.
+ bwc.setWritesAreBatched(true);
+
+ const NamespaceString nss{boost::none, "test", "coll"};
+ auto op = repl::MutableOplogEntry::makeDeleteOperation(nss, UUID::gen(), BSON("_id" << 0));
+ bwc.addBatchedOperation(opCtx, op);
+}
+
+DEATH_TEST_REGEX_F(BatchedWriteContextTest,
+ TestCannotGroupDDLOperation,
+ "Invariant failure.*getOpType.*repl::OpTypeEnum::kDelete.*kInsert.*kUpdate") {
+ auto opCtxRaii = makeOperationContext();
+ auto opCtx = opCtxRaii.get();
+
+ WriteUnitOfWork wuow(opCtx, /*groupOplogEntries=*/true);
+ auto& bwc = BatchedWriteContext::get(opCtx);
+ // Need to explicitly set writes are batched to simulate op observer starting batched write.
+ bwc.setWritesAreBatched(true);
+
+ const NamespaceString nss{NamespaceString(boost::none, "other", "coll")};
+ auto op = repl::MutableOplogEntry::makeCreateCommand(nss, CollectionOptions(), BSON("v" << 2));
+ bwc.addBatchedOperation(opCtx, op);
+}
+
+DEATH_TEST_REGEX_F(BatchedWriteContextTest,
+ TestDoesNotSupportPreImagesInCollection,
+ "Invariant "
+ "failure.*getChangeStreamPreImageRecordingMode.*repl::ReplOperation::"
+ "ChangeStreamPreImageRecordingMode::kOff") {
+ auto opCtxRaii = makeOperationContext();
+ auto opCtx = opCtxRaii.get();
+
+ WriteUnitOfWork wuow(opCtx, /*groupOplogEntries=*/true);
+ auto& bwc = BatchedWriteContext::get(opCtx);
+ // Need to explicitly set writes are batched to simulate op observer starting batched write.
+ bwc.setWritesAreBatched(true);
+
+ const NamespaceString nss{boost::none, "test", "coll"};
+ auto op = repl::MutableOplogEntry::makeDeleteOperation(nss, UUID::gen(), BSON("_id" << 0));
+ op.setChangeStreamPreImageRecordingMode(
+ repl::ReplOperation::ChangeStreamPreImageRecordingMode::kPreImagesCollection);
+ bwc.addBatchedOperation(opCtx, op);
+}
+
+DEATH_TEST_REGEX_F(BatchedWriteContextTest,
+ TestDoesNotSupportMultiDocTxn,
+ "Invariant failure.*!opCtx->inMultiDocumentTransaction()") {
+ auto opCtxRaii = makeOperationContext();
+ auto opCtx = opCtxRaii.get();
+ opCtx->setInMultiDocumentTransaction();
+
+ WriteUnitOfWork wuow(opCtx, /*groupOplogEntries=*/true);
+ auto& bwc = BatchedWriteContext::get(opCtx);
+ // Need to explicitly set writes are batched to simulate op observer starting batched write.
+ bwc.setWritesAreBatched(true);
+
+ const NamespaceString nss{boost::none, "test", "coll"};
+ auto op = repl::MutableOplogEntry::makeDeleteOperation(nss, UUID::gen(), BSON("_id" << 0));
+ bwc.addBatchedOperation(opCtx, op);
+}
+
+DEATH_TEST_REGEX_F(BatchedWriteContextTest,
+ TestDoesNotSupportRetryableWrites,
+ "Invariant failure.*!opCtx->getTxnNumber()") {
+ auto opCtxRaii = makeOperationContext();
+ auto opCtx = opCtxRaii.get();
+ opCtx->setLogicalSessionId(LogicalSessionId(makeLogicalSessionIdForTest()));
+ opCtx->setTxnNumber(TxnNumber{1});
+
+ WriteUnitOfWork wuow(opCtx, /*groupOplogEntries=*/true);
+ auto& bwc = BatchedWriteContext::get(opCtx);
+ // Need to explicitly set writes are batched to simulate op observer starting batched write.
+ bwc.setWritesAreBatched(true);
+
+ const NamespaceString nss{boost::none, "test", "coll"};
+ auto op = repl::MutableOplogEntry::makeDeleteOperation(nss, UUID::gen(), BSON("_id" << 0));
+ bwc.addBatchedOperation(opCtx, op);
+}
+
+TEST_F(BatchedWriteContextTest, TestAcceptedBatchOperationsSucceeds) {
+ auto opCtxRaii = makeOperationContext();
+ auto opCtx = opCtxRaii.get();
+ auto& bwc = BatchedWriteContext::get(opCtx);
+
+ WriteUnitOfWork wuow(opCtx, /*groupOplogEntries=*/true);
+ // Need to explicitly set writes are batched to simulate op observer
+ bwc.setWritesAreBatched(true);
+
+ BatchedWriteContext::BatchedOperations* ops = bwc.getBatchedOperations(opCtx);
+ ASSERT(ops->isEmpty());
+
+ const NamespaceString nss{boost::none, "test", "coll"};
+ auto op = repl::MutableOplogEntry::makeDeleteOperation(nss, UUID::gen(), BSON("_id" << 0));
+ bwc.addBatchedOperation(opCtx, op);
+ ASSERT_FALSE(ops->isEmpty());
+ ASSERT_EQ(ops->numOperations(), 1U);
+
+ op = repl::MutableOplogEntry::makeInsertOperation(
+ nss, UUID::gen(), BSON("a" << 0), BSON("_id" << 1));
+ bwc.addBatchedOperation(opCtx, op);
+ ASSERT_EQ(ops->numOperations(), 2U);
+
+ op = repl::MutableOplogEntry::makeInsertOperation(
+ nss, UUID::gen(), BSON("a" << 1), BSON("_id" << 2));
+ bwc.addBatchedOperation(opCtx, op);
+ ASSERT_EQ(ops->numOperations(), 3U);
+
+ // Batched write committing is handled outside of the batched write context and involves the
+ // oplog so it is not necessary to commit the WriteUnitOfWork in this test.
+ bwc.clearBatchedOperations(opCtx);
+ ASSERT(ops->isEmpty());
+}
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/db/op_observer/op_observer_impl_test.cpp b/src/mongo/db/op_observer/op_observer_impl_test.cpp
index b1a68e225d7..f89cd995179 100644
--- a/src/mongo/db/op_observer/op_observer_impl_test.cpp
+++ b/src/mongo/db/op_observer/op_observer_impl_test.cpp
@@ -2698,63 +2698,6 @@ protected:
const NamespaceString _nssWithTid{TenantId(OID::gen()), "test", "coll"};
};
-DEATH_TEST_REGEX_F(BatchedWriteOutputsTest,
- TestCannotGroupDDLOperation,
- "Invariant failure.*getOpType.*repl::OpTypeEnum::kDelete.*kInsert.*kUpdate") {
- auto opCtxRaii = cc().makeOperationContext();
- OperationContext* opCtx = opCtxRaii.get();
- WriteUnitOfWork wuow(opCtx, true /* groupOplogEntries */);
-
- auto& bwc = BatchedWriteContext::get(opCtx);
- bwc.addBatchedOperation(
- opCtx,
- repl::MutableOplogEntry::makeCreateCommand(
- NamespaceString(boost::none, "other", "coll"), CollectionOptions(), BSON("v" << 2)));
-}
-
-DEATH_TEST_REGEX_F(BatchedWriteOutputsTest,
- TestDoesNotSupportPreImagesInCollection,
- "Invariant "
- "failure.*getChangeStreamPreImageRecordingMode.*repl::ReplOperation::"
- "ChangeStreamPreImageRecordingMode::kOff") {
- auto opCtxRaii = cc().makeOperationContext();
- OperationContext* opCtx = opCtxRaii.get();
- WriteUnitOfWork wuow(opCtx, true /* groupOplogEntries */);
-
- auto& bwc = BatchedWriteContext::get(opCtx);
- auto entry = repl::MutableOplogEntry::makeDeleteOperation(_nss, UUID::gen(), BSON("_id" << 0));
- entry.setChangeStreamPreImageRecordingMode(
- repl::ReplOperation::ChangeStreamPreImageRecordingMode::kPreImagesCollection);
- bwc.addBatchedOperation(opCtx, entry);
-}
-
-DEATH_TEST_REGEX_F(BatchedWriteOutputsTest,
- TestDoesNotSupportMultiDocTxn,
- "Invariant failure.*!opCtx->inMultiDocumentTransaction()") {
- auto opCtxRaii = cc().makeOperationContext();
- OperationContext* opCtx = opCtxRaii.get();
- opCtx->setInMultiDocumentTransaction();
- WriteUnitOfWork wuow(opCtx, true /* groupOplogEntries */);
-
- auto& bwc = BatchedWriteContext::get(opCtx);
- auto entry = repl::MutableOplogEntry::makeDeleteOperation(_nss, UUID::gen(), BSON("_id" << 0));
- bwc.addBatchedOperation(opCtx, entry);
-}
-
-DEATH_TEST_REGEX_F(BatchedWriteOutputsTest,
- TestDoesNotSupportRetryableWrites,
- "Invariant failure.*!opCtx->getTxnNumber()") {
- auto opCtxRaii = cc().makeOperationContext();
- OperationContext* opCtx = opCtxRaii.get();
- opCtx->setLogicalSessionId(LogicalSessionId(makeLogicalSessionIdForTest()));
- opCtx->setTxnNumber(TxnNumber{1});
- WriteUnitOfWork wuow(opCtx, true /* groupOplogEntries */);
-
- auto& bwc = BatchedWriteContext::get(opCtx);
- auto entry = repl::MutableOplogEntry::makeDeleteOperation(_nss, UUID::gen(), BSON("_id" << 0));
- bwc.addBatchedOperation(opCtx, entry);
-}
-
// Verifies that a WriteUnitOfWork with groupOplogEntries=true replicates its writes as a single
// applyOps. Tests WUOWs batching a range of 1 to 5 deletes (inclusive).
TEST_F(BatchedWriteOutputsTest, TestApplyOpsGrouping) {