diff options
author | Randolph Tan <randolph@10gen.com> | 2017-08-18 20:19:59 -0400 |
---|---|---|
committer | Randolph Tan <randolph@10gen.com> | 2017-08-26 02:14:50 -0400 |
commit | dc8a9cc980e84734d90ffc0f71c50c123cdd9543 (patch) | |
tree | 3357fd45cf8d3ddfdae938aed58a85e545a14344 | |
parent | ec42f5f16ff7809c5b1ed29601978e9e98aa5925 (diff) | |
download | mongo-dc8a9cc980e84734d90ffc0f71c50c123cdd9543.tar.gz |
SERVER-28914 Create a test fixture with mock replication coordinator and ephemeral storage engine
-rw-r--r-- | src/mongo/db/SConscript | 6 | ||||
-rw-r--r-- | src/mongo/db/ops/SConscript | 3 | ||||
-rw-r--r-- | src/mongo/db/ops/write_ops_retryability_test.cpp | 72 | ||||
-rw-r--r-- | src/mongo/db/repl/SConscript | 12 | ||||
-rw-r--r-- | src/mongo/db/repl/mock_repl_coord_server_fixture.cpp | 91 | ||||
-rw-r--r-- | src/mongo/db/repl/mock_repl_coord_server_fixture.h | 63 | ||||
-rw-r--r-- | src/mongo/db/session_test.cpp | 86 | ||||
-rw-r--r-- | src/mongo/db/transaction_history_iterator_test.cpp | 58 |
8 files changed, 201 insertions, 190 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index b74534df190..1302ce14683 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -1528,8 +1528,7 @@ env.CppUnitTest( 'session_test.cpp', ], LIBDEPS=[ - '$BUILD_DIR/mongo/db/repl/replmocks', - 'service_context_d_test_fixture', + '$BUILD_DIR/mongo/db/repl/mock_repl_coord_server_fixture', 'write_ops', ], ) @@ -1540,8 +1539,7 @@ env.CppUnitTest( 'transaction_history_iterator_test.cpp', ], LIBDEPS=[ - '$BUILD_DIR/mongo/db/repl/replmocks', - 'service_context_d_test_fixture', + '$BUILD_DIR/mongo/db/repl/mock_repl_coord_server_fixture', 'write_ops', ], ) diff --git a/src/mongo/db/ops/SConscript b/src/mongo/db/ops/SConscript index ec3fd359719..2254606f570 100644 --- a/src/mongo/db/ops/SConscript +++ b/src/mongo/db/ops/SConscript @@ -188,9 +188,8 @@ env.CppUnitTest( target='write_ops_retryability_test', source='write_ops_retryability_test.cpp', LIBDEPS=[ + '$BUILD_DIR/mongo/db/repl/mock_repl_coord_server_fixture', '$BUILD_DIR/mongo/db/repl/oplog_entry', - '$BUILD_DIR/mongo/db/repl/replmocks', - '$BUILD_DIR/mongo/db/service_context_d_test_fixture', '$BUILD_DIR/mongo/db/write_ops', ], ) diff --git a/src/mongo/db/ops/write_ops_retryability_test.cpp b/src/mongo/db/ops/write_ops_retryability_test.cpp index 86f581659ba..78dcc32bc39 100644 --- a/src/mongo/db/ops/write_ops_retryability_test.cpp +++ b/src/mongo/db/ops/write_ops_retryability_test.cpp @@ -36,6 +36,7 @@ #include "mongo/db/ops/write_ops.h" #include "mongo/db/ops/write_ops_retryability.h" #include "mongo/db/query/find_and_modify_request.h" +#include "mongo/db/repl/mock_repl_coord_server_fixture.h" #include "mongo/db/repl/oplog_entry.h" #include "mongo/db/repl/replication_coordinator_mock.h" #include "mongo/db/service_context.h" @@ -117,62 +118,7 @@ TEST_F(WriteOpsRetryability, ParseOplogEntryForDelete) { ASSERT_BSONOBJ_EQ(res.getUpsertedId(), BSONObj()); } -class FindAndModifyRetryability : public ServiceContextMongoDTest { -public: - void setUp() override { - ServiceContextMongoDTest::setUp(); - - _opCtx = cc().makeOperationContext(); - - // Insert code path assumes existence of repl coordinator! - repl::ReplSettings replSettings; - replSettings.setReplSetString( - ConnectionString::forReplicaSet("sessionTxnStateTest", {HostAndPort("a:1")}) - .toString()); - replSettings.setMaster(true); - - auto service = getServiceContext(); - repl::ReplicationCoordinator::set( - service, stdx::make_unique<repl::ReplicationCoordinatorMock>(service, replSettings)); - - // Note: internal code does not allow implicit creation of non-capped oplog collection. - DBDirectClient client(opCtx()); - ASSERT_TRUE( - client.createCollection(NamespaceString::kRsOplogNamespace.ns(), 1024 * 1024, true)); - } - - void tearDown() override { - // ServiceContextMongoDTest::tearDown() will try to create it's own opCtx, and it's not - // allowed to have 2 present per client, so destroy this one. - _opCtx.reset(); - - ServiceContextMongoDTest::tearDown(); - } - - /** - * Helper method for inserting new entries to the oplog. This completely bypasses - * fixDocumentForInsert. - */ - void insertOplogEntry(BSONObj entry) { - AutoGetCollection autoColl(opCtx(), NamespaceString::kRsOplogNamespace, MODE_IX); - auto coll = autoColl.getCollection(); - ASSERT_TRUE(coll != nullptr); - - auto status = coll->insertDocument(opCtx(), - InsertStatement(entry), - &CurOp::get(opCtx())->debug(), - /* enforceQuota */ false, - /* fromMigrate */ false); - ASSERT_OK(status); - } - - OperationContext* opCtx() { - return _opCtx.get(); - } - -private: - ServiceContext::UniqueOperationContext _opCtx; -}; +using FindAndModifyRetryability = MockReplCoordServerFixture; NamespaceString kNs("test.user"); @@ -200,7 +146,7 @@ TEST_F(FindAndModifyRetryability, ErrorIfRequestIsUpsertButOplogIsUpdate) { repl::OplogEntry noteOplog( repl::OpTime(imageTs, 1), 0, repl::OpTypeEnum::kNoop, kNs, BSON("x" << 1 << "z" << 1)); - insertOplogEntry(noteOplog.toBSON()); + insertOplogEntry(noteOplog); repl::OplogEntry oplog( repl::OpTime(), 0, repl::OpTypeEnum::kUpdate, kNs, BSON("x" << 1), BSON("y" << 1)); @@ -227,7 +173,7 @@ TEST_F(FindAndModifyRetryability, ErrorIfRequestIsPostImageButOplogHasPre) { repl::OplogEntry noteOplog( repl::OpTime(imageTs, 1), 0, repl::OpTypeEnum::kNoop, kNs, BSON("x" << 1 << "z" << 1)); - insertOplogEntry(noteOplog.toBSON()); + insertOplogEntry(noteOplog); repl::OplogEntry updateOplog(repl::OpTime(), 0, @@ -249,7 +195,7 @@ TEST_F(FindAndModifyRetryability, ErrorIfRequestIsUpdateButOplogIsDelete) { repl::OplogEntry noteOplog( repl::OpTime(imageTs, 1), 0, repl::OpTypeEnum::kNoop, kNs, BSON("x" << 1 << "z" << 1)); - insertOplogEntry(noteOplog.toBSON()); + insertOplogEntry(noteOplog); repl::OplogEntry oplog(repl::OpTime(), 0, repl::OpTypeEnum::kDelete, kNs, BSON("_id" << 1)); oplog.setPreImageTs(imageTs); @@ -265,7 +211,7 @@ TEST_F(FindAndModifyRetryability, ErrorIfRequestIsPreImageButOplogHasPost) { repl::OplogEntry noteOplog( repl::OpTime(imageTs, 1), 0, repl::OpTypeEnum::kNoop, kNs, BSON("x" << 1 << "z" << 1)); - insertOplogEntry(noteOplog.toBSON()); + insertOplogEntry(noteOplog); repl::OplogEntry updateOplog(repl::OpTime(), 0, @@ -287,7 +233,7 @@ TEST_F(FindAndModifyRetryability, UpdateWithPreImage) { repl::OplogEntry noteOplog( repl::OpTime(imageTs, 1), 0, repl::OpTypeEnum::kNoop, kNs, BSON("x" << 1 << "z" << 1)); - insertOplogEntry(noteOplog.toBSON()); + insertOplogEntry(noteOplog); repl::OplogEntry updateOplog(repl::OpTime(), 0, @@ -315,7 +261,7 @@ TEST_F(FindAndModifyRetryability, UpdateWithPostImage) { repl::OplogEntry noteOplog( repl::OpTime(imageTs, 1), 0, repl::OpTypeEnum::kNoop, kNs, BSON("a" << 1 << "b" << 1)); - insertOplogEntry(noteOplog.toBSON()); + insertOplogEntry(noteOplog); repl::OplogEntry updateOplog(repl::OpTime(), 0, @@ -359,7 +305,7 @@ TEST_F(FindAndModifyRetryability, BasicRemove) { repl::OplogEntry noteOplog( repl::OpTime(imageTs, 1), 0, repl::OpTypeEnum::kNoop, kNs, BSON("_id" << 20 << "a" << 1)); - insertOplogEntry(noteOplog.toBSON()); + insertOplogEntry(noteOplog); repl::OplogEntry removeOplog( repl::OpTime(), 0, repl::OpTypeEnum::kDelete, kNs, BSON("_id" << 20)); diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript index 117de59f608..105e279b774 100644 --- a/src/mongo/db/repl/SConscript +++ b/src/mongo/db/repl/SConscript @@ -1602,3 +1602,15 @@ env.Library( 'sync_tail', ], ) + +env.Library( + target='mock_repl_coord_server_fixture', + source=[ + 'mock_repl_coord_server_fixture.cpp', + ], + LIBDEPS=[ + 'replmocks', + '$BUILD_DIR/mongo/db/service_context_d_test_fixture', + ] +) + diff --git a/src/mongo/db/repl/mock_repl_coord_server_fixture.cpp b/src/mongo/db/repl/mock_repl_coord_server_fixture.cpp new file mode 100644 index 00000000000..1389a8caf94 --- /dev/null +++ b/src/mongo/db/repl/mock_repl_coord_server_fixture.cpp @@ -0,0 +1,91 @@ +/** + * Copyright (C) 2017 MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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 + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * 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 GNU Affero General 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/platform/basic.h" + +#include "mongo/db/repl/mock_repl_coord_server_fixture.h" + +#include "mongo/db/client.h" +#include "mongo/db/curop.h" +#include "mongo/db/db_raii.h" +#include "mongo/db/dbdirectclient.h" +#include "mongo/db/operation_context.h" +#include "mongo/db/repl/oplog_entry.h" +#include "mongo/db/repl/replication_coordinator_mock.h" +#include "mongo/db/service_context.h" +#include "mongo/db/service_context_d_test_fixture.h" + +namespace mongo { + +void MockReplCoordServerFixture::setUp() { + ServiceContextMongoDTest::setUp(); + + _opCtx = cc().makeOperationContext(); + + // Insert code path assumes existence of repl coordinator! + repl::ReplSettings replSettings; + replSettings.setReplSetString( + ConnectionString::forReplicaSet("sessionTxnStateTest", {HostAndPort("a:1")}).toString()); + replSettings.setMaster(true); + + auto service = getServiceContext(); + repl::ReplicationCoordinator::set( + service, stdx::make_unique<repl::ReplicationCoordinatorMock>(service, replSettings)); + + // Note: internal code does not allow implicit creation of non-capped oplog collection. + DBDirectClient client(opCtx()); + ASSERT_TRUE( + client.createCollection(NamespaceString::kRsOplogNamespace.ns(), 1024 * 1024, true)); +} + +void MockReplCoordServerFixture::tearDown() { + // ServiceContextMongoDTest::tearDown() will try to create it's own opCtx, and it's not + // allowed to have 2 present per client, so destroy this one. + _opCtx.reset(); + + ServiceContextMongoDTest::tearDown(); +} + +void MockReplCoordServerFixture::insertOplogEntry(const repl::OplogEntry& entry) { + AutoGetCollection autoColl(opCtx(), NamespaceString::kRsOplogNamespace, MODE_IX); + auto coll = autoColl.getCollection(); + ASSERT_TRUE(coll != nullptr); + + auto status = coll->insertDocument(opCtx(), + InsertStatement(entry.toBSON()), + &CurOp::get(opCtx())->debug(), + /* enforceQuota */ false, + /* fromMigrate */ false); + ASSERT_OK(status); +} + +OperationContext* MockReplCoordServerFixture::opCtx() { + return _opCtx.get(); +} + +} // namespace mongo diff --git a/src/mongo/db/repl/mock_repl_coord_server_fixture.h b/src/mongo/db/repl/mock_repl_coord_server_fixture.h new file mode 100644 index 00000000000..71f1fa06fec --- /dev/null +++ b/src/mongo/db/repl/mock_repl_coord_server_fixture.h @@ -0,0 +1,63 @@ +/** + * Copyright (C) 2017 MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * 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 + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * 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 GNU Affero General 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/operation_context.h" +#include "mongo/db/service_context.h" +#include "mongo/db/service_context_d_test_fixture.h" +#include "mongo/unittest/unittest.h" + +namespace mongo { + +class OperationContext; + +namespace repl { +class OplogEntry; +} + +/** + * This is a basic fixture that is backed by an ephemeral storage engine and a mock replication + * coordinator that is running as primary. + */ +class MockReplCoordServerFixture : public ServiceContextMongoDTest { +public: + void setUp() override; + void tearDown() override; + + /** + * Helper method for inserting new entries to the oplog. This completely bypasses + * fixDocumentForInsert. + */ + void insertOplogEntry(const repl::OplogEntry& entry); + + OperationContext* opCtx(); + +private: + ServiceContext::UniqueOperationContext _opCtx; +}; + +} // namespace mongo diff --git a/src/mongo/db/session_test.cpp b/src/mongo/db/session_test.cpp index 0170a9f03fd..f9864e8ad2f 100644 --- a/src/mongo/db/session_test.cpp +++ b/src/mongo/db/session_test.cpp @@ -36,6 +36,7 @@ #include "mongo/db/db_raii.h" #include "mongo/db/dbdirectclient.h" #include "mongo/db/operation_context.h" +#include "mongo/db/repl/mock_repl_coord_server_fixture.h" #include "mongo/db/repl/oplog.h" #include "mongo/db/repl/oplog_entry.h" #include "mongo/db/repl/optime.h" @@ -49,65 +50,16 @@ namespace mongo { namespace { -class SessionTest : public ServiceContextMongoDTest { +class SessionTest : public MockReplCoordServerFixture { public: void setUp() override { - ServiceContextMongoDTest::setUp(); - - _opCtx = cc().makeOperationContext(); - - // Insert code path assumes existence of repl coordinator! - repl::ReplSettings replSettings; - replSettings.setReplSetString( - ConnectionString::forReplicaSet("sessionTxnStateTest", {HostAndPort("a:1")}) - .toString()); - replSettings.setMaster(true); - - auto service = getServiceContext(); - repl::ReplicationCoordinator::set( - service, stdx::make_unique<repl::ReplicationCoordinatorMock>(service, replSettings)); + MockReplCoordServerFixture::setUp(); + auto service = opCtx()->getServiceContext(); SessionCatalog::reset_forTest(service); SessionCatalog::create(service); - SessionCatalog::get(service)->onStepUp(_opCtx.get()); - - // Note: internal code does not allow implicit creation of non-capped oplog collection. - DBDirectClient client(opCtx()); - ASSERT_TRUE( - client.createCollection(NamespaceString::kRsOplogNamespace.ns(), 1024 * 1024, true)); - } - - void tearDown() override { - // ServiceContextMongoDTest::tearDown() will try to create it's own opCtx, and it's not - // allowed to have 2 present per client, so destroy this one. - _opCtx.reset(); - - ServiceContextMongoDTest::tearDown(); + SessionCatalog::get(service)->onStepUp(opCtx()); } - - /** - * Helper method for inserting new entries to the oplog. This completely bypasses - * fixDocumentForInsert. - */ - void insertOplogEntry(BSONObj entry) { - AutoGetCollection autoColl(opCtx(), NamespaceString::kRsOplogNamespace, MODE_IX); - auto coll = autoColl.getCollection(); - ASSERT_TRUE(coll != nullptr); - - auto status = coll->insertDocument(opCtx(), - InsertStatement(entry), - &CurOp::get(opCtx())->debug(), - /* enforceQuota */ false, - /* fromMigrate */ false); - ASSERT_OK(status); - } - - OperationContext* opCtx() { - return _opCtx.get(); - } - -private: - ServiceContext::UniqueOperationContext _opCtx; }; TEST_F(SessionTest, CanCreateNewSessionEntry) { @@ -514,18 +466,22 @@ TEST_F(SessionTest, CheckStatementExecuted) { // Returns the correct oplog entry if the statement has completed. auto optimeTs = Timestamp(50, 10); - insertOplogEntry(BSON("ts" << optimeTs << "t" << 1LL << "h" << 0LL << "op" - << "i" - << "ns" - << "a.b" - << "o" - << BSON("_id" << 1 << "x" << 5) - << "txnNumber" - << txnNum - << "stmtId" - << stmtId - << "prevTs" - << Timestamp(0, 0))); + + OperationSessionInfo opSessionInfo; + opSessionInfo.setSessionId(sessionId); + opSessionInfo.setTxnNumber(txnNum); + + repl::OplogEntry oplogEntry(repl::OpTime(optimeTs, 1), + 0, + repl::OpTypeEnum::kInsert, + NamespaceString("a.b"), + 0, + BSON("_id" << 1 << "x" << 5)); + oplogEntry.setOperationSessionInfo(opSessionInfo); + oplogEntry.setStatementId(stmtId); + oplogEntry.setPrevWriteTsInTransaction(Timestamp(0, 0)); + insertOplogEntry(oplogEntry); + { AutoGetCollection autoColl(opCtx(), NamespaceString("a.b"), MODE_IX); WriteUnitOfWork wuow(opCtx()); diff --git a/src/mongo/db/transaction_history_iterator_test.cpp b/src/mongo/db/transaction_history_iterator_test.cpp index 18464573f94..687ced1b8cf 100644 --- a/src/mongo/db/transaction_history_iterator_test.cpp +++ b/src/mongo/db/transaction_history_iterator_test.cpp @@ -37,6 +37,7 @@ #include "mongo/db/dbdirectclient.h" #include "mongo/db/namespace_string.h" #include "mongo/db/operation_context.h" +#include "mongo/db/repl/mock_repl_coord_server_fixture.h" #include "mongo/db/repl/oplog.h" #include "mongo/db/repl/oplog_entry.h" #include "mongo/db/repl/optime.h" @@ -49,62 +50,7 @@ namespace mongo { -class SessionHistoryIteratorTest : public ServiceContextMongoDTest { -public: - void setUp() override { - ServiceContextMongoDTest::setUp(); - - _opCtx = cc().makeOperationContext(); - - // Insert code path assumes existence of repl coordinator! - repl::ReplSettings replSettings; - replSettings.setReplSetString( - ConnectionString::forReplicaSet("sessionTxnStateTest", {HostAndPort("a:1")}) - .toString()); - replSettings.setMaster(true); - - auto service = getServiceContext(); - repl::ReplicationCoordinator::set( - service, stdx::make_unique<repl::ReplicationCoordinatorMock>(service, replSettings)); - - // Note: internal code does not allow implicit creation of non-capped oplog collection. - DBDirectClient client(opCtx()); - ASSERT_TRUE( - client.createCollection(NamespaceString::kRsOplogNamespace.ns(), 1024 * 1024, true)); - } - - void tearDown() override { - // ServiceContextMongoDTest::tearDown() will try to create it's own opCtx, and it's not - // allowed to have 2 present per client, so destroy this one. - _opCtx.reset(); - - ServiceContextMongoDTest::tearDown(); - } - - /** - * Helper method for inserting new entries to the oplog. This completely bypasses - * fixDocumentForInsert. - */ - void insertOplogEntry(const repl::OplogEntry newOplog) { - AutoGetCollection autoColl(opCtx(), NamespaceString::kRsOplogNamespace, MODE_IX); - auto coll = autoColl.getCollection(); - ASSERT_TRUE(coll != nullptr); - - auto status = coll->insertDocument(opCtx(), - InsertStatement(newOplog.toBSON()), - &CurOp::get(opCtx())->debug(), - /* enforceQuota */ false, - /* fromMigrate */ false); - ASSERT_OK(status); - } - - OperationContext* opCtx() { - return _opCtx.get(); - } - -private: - ServiceContext::UniqueOperationContext _opCtx; -}; +using SessionHistoryIteratorTest = MockReplCoordServerFixture; TEST_F(SessionHistoryIteratorTest, NormalHistory) { repl::OplogEntry entry1(repl::OpTime(Timestamp(52, 345), 2), |