diff options
author | Shin Yee Tan <shinyee.tan@mongodb.com> | 2022-12-21 15:09:50 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-12-21 15:39:20 +0000 |
commit | 3b467e88d14c42e789b62d1edb2ab06aec765f4f (patch) | |
tree | 57214ea3b9cb9ab7b4c05a325bdd948ab53588c5 | |
parent | 82c46f01769d6cbae70a27ff948b0d93c49f7420 (diff) | |
download | mongo-3b467e88d14c42e789b62d1edb2ab06aec765f4f.tar.gz |
SERVER-71190 Create unittest for batched write context
-rw-r--r-- | src/mongo/db/op_observer/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/db/op_observer/batched_write_context_test.cpp | 194 | ||||
-rw-r--r-- | src/mongo/db/op_observer/op_observer_impl_test.cpp | 57 |
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) { |