summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJudah Schvimer <judah@mongodb.com>2017-11-09 10:37:47 -0500
committerJudah Schvimer <judah@mongodb.com>2017-11-09 10:37:47 -0500
commit54a3f40dcfbff57f46859ba0b88249e6008597ea (patch)
tree73621af61ad9b3c217f1c3b8399c8d9d2cb8caea
parent271879b7a67c9d9b36778692f2a77e04c6403a1f (diff)
downloadmongo-54a3f40dcfbff57f46859ba0b88249e6008597ea.tar.gz
SERVER-31805 Set local collection validation options correctly in rollbackViaRefetchNoUUID
-rw-r--r--src/mongo/db/repl/SConscript3
-rw-r--r--src/mongo/db/repl/rollback_test_fixture.cpp163
-rw-r--r--src/mongo/db/repl/rollback_test_fixture.h79
-rw-r--r--src/mongo/db/repl/rs_rollback_no_uuid.cpp21
-rw-r--r--src/mongo/db/repl/rs_rollback_no_uuid_test.cpp181
-rw-r--r--src/mongo/db/repl/rs_rollback_test.cpp191
6 files changed, 330 insertions, 308 deletions
diff --git a/src/mongo/db/repl/SConscript b/src/mongo/db/repl/SConscript
index 363fe9334a4..f456284ecf9 100644
--- a/src/mongo/db/repl/SConscript
+++ b/src/mongo/db/repl/SConscript
@@ -538,6 +538,7 @@ env.Library(
'rollback_test_fixture.cpp',
],
LIBDEPS=[
+ 'oplog_interface_mock',
'optime',
'replication_process',
'replmocks',
@@ -556,7 +557,6 @@ env.CppUnitTest(
],
LIBDEPS=[
'oplog_interface_local',
- 'oplog_interface_mock',
'rollback_test_fixture',
'rs_rollback',
],
@@ -569,7 +569,6 @@ env.CppUnitTest(
],
LIBDEPS=[
'oplog_interface_local',
- 'oplog_interface_mock',
'rollback_test_fixture',
'rs_rollback_no_uuid',
],
diff --git a/src/mongo/db/repl/rollback_test_fixture.cpp b/src/mongo/db/repl/rollback_test_fixture.cpp
index 7208953e6b5..83e2ed8687a 100644
--- a/src/mongo/db/repl/rollback_test_fixture.cpp
+++ b/src/mongo/db/repl/rollback_test_fixture.cpp
@@ -32,13 +32,18 @@
#include <string>
+#include "mongo/db/catalog/collection_catalog_entry.h"
+#include "mongo/db/catalog/database_holder.h"
#include "mongo/db/client.h"
+#include "mongo/db/db_raii.h"
#include "mongo/db/repl/oplog.h"
#include "mongo/db/repl/replication_consistency_markers_mock.h"
#include "mongo/db/repl/replication_coordinator.h"
#include "mongo/db/repl/replication_coordinator_mock.h"
#include "mongo/db/repl/replication_process.h"
#include "mongo/db/repl/replication_recovery_mock.h"
+#include "mongo/db/repl/rs_rollback.h"
+#include "mongo/db/repl/rs_rollback_no_uuid.h"
#include "mongo/db/session_catalog.h"
#include "mongo/logger/log_component.h"
#include "mongo/logger/logger.h"
@@ -132,5 +137,163 @@ Status RollbackTest::ReplicationCoordinatorRollbackMock::setFollowerMode(
return ReplicationCoordinatorMock::setFollowerMode(newState);
}
+std::pair<BSONObj, RecordId> RollbackTest::makeCommandOp(
+ Timestamp ts, OptionalCollectionUUID uuid, StringData nss, BSONObj cmdObj, int recordId) {
+
+ BSONObjBuilder bob;
+ bob.append("ts", ts);
+ bob.append("h", 1LL);
+ bob.append("op", "c");
+ if (uuid) { // Not all ops have UUID fields.
+ uuid.get().appendToBuilder(&bob, "ui");
+ }
+ bob.append("ns", nss);
+ bob.append("o", cmdObj);
+
+ return std::make_pair(bob.obj(), RecordId(recordId));
+}
+
+Collection* RollbackTest::_createCollection(OperationContext* opCtx,
+ const NamespaceString& nss,
+ const CollectionOptions& options) {
+ Lock::DBLock dbLock(opCtx, nss.db(), MODE_X);
+ mongo::WriteUnitOfWork wuow(opCtx);
+ auto db = dbHolder().openDb(opCtx, nss.db());
+ ASSERT_TRUE(db);
+ db->dropCollection(opCtx, nss.ns()).transitional_ignore();
+ auto coll = db->createCollection(opCtx, nss.ns(), options);
+ ASSERT_TRUE(coll);
+ wuow.commit();
+ return coll;
+}
+
+Collection* RollbackTest::_createCollection(OperationContext* opCtx,
+ const std::string& nss,
+ const CollectionOptions& options) {
+ return _createCollection(opCtx, NamespaceString(nss), options);
+}
+
+RollbackSourceMock::RollbackSourceMock(std::unique_ptr<OplogInterface> oplog)
+ : _oplog(std::move(oplog)) {}
+
+const OplogInterface& RollbackSourceMock::getOplog() const {
+ return *_oplog;
+}
+
+const HostAndPort& RollbackSourceMock::getSource() const {
+ return _source;
+}
+
+int RollbackSourceMock::getRollbackId() const {
+ return 0;
+}
+
+BSONObj RollbackSourceMock::getLastOperation() const {
+ auto iter = _oplog->makeIterator();
+ auto result = iter->next();
+ ASSERT_OK(result.getStatus());
+ return result.getValue().first;
+}
+
+BSONObj RollbackSourceMock::findOne(const NamespaceString& nss, const BSONObj& filter) const {
+ return BSONObj();
+}
+
+std::pair<BSONObj, NamespaceString> RollbackSourceMock::findOneByUUID(const std::string& db,
+ UUID uuid,
+ const BSONObj& filter) const {
+ return {BSONObj(), NamespaceString()};
+}
+
+void RollbackSourceMock::copyCollectionFromRemote(OperationContext* opCtx,
+ const NamespaceString& nss) const {}
+
+StatusWith<BSONObj> RollbackSourceMock::getCollectionInfo(const NamespaceString& nss) const {
+ return BSON("name" << nss.ns() << "options" << BSONObj());
+}
+
+StatusWith<BSONObj> RollbackSourceMock::getCollectionInfoByUUID(const std::string& db,
+ const UUID& uuid) const {
+ return BSON("options" << BSONObj() << "info" << BSON("uuid" << uuid));
+}
+
+RollbackResyncsCollectionOptionsTest::RollbackSourceWithCollectionOptions::
+ RollbackSourceWithCollectionOptions(std::unique_ptr<OplogInterface> oplog,
+ BSONObj collOptionsObj)
+ : RollbackSourceMock(std::move(oplog)), collOptionsObj(collOptionsObj) {}
+
+
+StatusWith<BSONObj>
+RollbackResyncsCollectionOptionsTest::RollbackSourceWithCollectionOptions::getCollectionInfo(
+ const NamespaceString& nss) const {
+ calledNoUUID = true;
+ return BSON("options" << collOptionsObj);
+}
+
+StatusWith<BSONObj>
+RollbackResyncsCollectionOptionsTest::RollbackSourceWithCollectionOptions::getCollectionInfoByUUID(
+ const std::string& db, const UUID& uuid) const {
+ calledWithUUID = true;
+ return BSON("options" << collOptionsObj << "info" << BSON("uuid" << uuid));
+}
+
+void RollbackResyncsCollectionOptionsTest::resyncCollectionOptionsTest(
+ CollectionOptions localCollOptions, BSONObj remoteCollOptionsObj) {
+ createOplog(_opCtx.get());
+
+ auto dbName = "test";
+ auto collName = "coll";
+ auto nss = NamespaceString(dbName, collName);
+
+ auto coll = _createCollection(_opCtx.get(), nss.toString(), localCollOptions);
+ auto commonOperation =
+ std::make_pair(BSON("ts" << Timestamp(Seconds(1), 0) << "h" << 1LL), RecordId(1));
+
+ // 'collMod' operation used to trigger metadata re-sync.
+ BSONObj collModCmd = BSON("collMod" << collName << "noPadding" << false);
+ auto collectionModificationOperation =
+ makeCommandOp(Timestamp(Seconds(2), 0), coll->uuid(), nss.toString(), collModCmd, 2);
+
+ RollbackSourceWithCollectionOptions rollbackSource(
+ std::unique_ptr<OplogInterface>(new OplogInterfaceMock({commonOperation})),
+ remoteCollOptionsObj);
+
+ if (coll->uuid()) {
+ ASSERT_OK(
+ syncRollback(_opCtx.get(),
+ OplogInterfaceMock({collectionModificationOperation, commonOperation}),
+ rollbackSource,
+ {},
+ _coordinator,
+ _replicationProcess.get()));
+
+ ASSERT_TRUE(rollbackSource.calledWithUUID);
+ ASSERT_FALSE(rollbackSource.calledNoUUID);
+ } else {
+ ASSERT_OK(syncRollbackNoUUID(
+ _opCtx.get(),
+ OplogInterfaceMock({collectionModificationOperation, commonOperation}),
+ rollbackSource,
+ {},
+ _coordinator,
+ _replicationProcess.get()));
+
+ ASSERT_TRUE(rollbackSource.calledNoUUID);
+ ASSERT_FALSE(rollbackSource.calledWithUUID);
+ }
+
+ // Make sure the collection options are correct.
+ AutoGetCollectionForReadCommand autoColl(_opCtx.get(), NamespaceString(nss.toString()));
+ auto collAfterRollbackOptions =
+ autoColl.getCollection()->getCatalogEntry()->getCollectionOptions(_opCtx.get());
+
+ BSONObjBuilder expectedOptionsBob;
+ if (localCollOptions.uuid) {
+ localCollOptions.uuid.get().appendToBuilder(&expectedOptionsBob, "uuid");
+ }
+ expectedOptionsBob.appendElements(remoteCollOptionsObj);
+
+ ASSERT_BSONOBJ_EQ(expectedOptionsBob.obj(), collAfterRollbackOptions.toBSON());
+}
} // namespace repl
} // namespace mongo
diff --git a/src/mongo/db/repl/rollback_test_fixture.h b/src/mongo/db/repl/rollback_test_fixture.h
index 0f86cf4d97c..c24ba1bcffa 100644
--- a/src/mongo/db/repl/rollback_test_fixture.h
+++ b/src/mongo/db/repl/rollback_test_fixture.h
@@ -29,8 +29,11 @@
#pragma once
#include "mongo/db/repl/drop_pending_collection_reaper.h"
+#include "mongo/db/repl/oplog_interface.h"
+#include "mongo/db/repl/oplog_interface_mock.h"
#include "mongo/db/repl/replication_coordinator_mock.h"
#include "mongo/db/repl/replication_process.h"
+#include "mongo/db/repl/rollback_source.h"
#include "mongo/db/repl/storage_interface_impl.h"
#include "mongo/db/service_context.h"
#include "mongo/db/service_context_d_test_fixture.h"
@@ -63,6 +66,22 @@ public:
*/
void tearDown() override;
+ /**
+ * Creates a collection with the given namespace and options.
+ */
+ static Collection* _createCollection(OperationContext* opCtx,
+ const NamespaceString& nss,
+ const CollectionOptions& options);
+ static Collection* _createCollection(OperationContext* opCtx,
+ const std::string& nss,
+ const CollectionOptions& options);
+
+ /**
+ * Creates an oplog entry with a recordId for a command operation.
+ */
+ static std::pair<BSONObj, RecordId> makeCommandOp(
+ Timestamp ts, OptionalCollectionUUID uuid, StringData nss, BSONObj cmdObj, int recordId);
+
protected:
// Test fixture used to manage the service context and global storage engine.
ServiceContextMongoDTest _serviceContextMongoDTest;
@@ -118,5 +137,65 @@ private:
ErrorCodes::Error _failSetFollowerModeWithThisCode = ErrorCodes::InternalError;
};
+class RollbackSourceMock : public RollbackSource {
+public:
+ RollbackSourceMock(std::unique_ptr<OplogInterface> oplog);
+ int getRollbackId() const override;
+ const OplogInterface& getOplog() const override;
+ const HostAndPort& getSource() const override;
+ BSONObj getLastOperation() const override;
+ BSONObj findOne(const NamespaceString& nss, const BSONObj& filter) const override;
+
+ std::pair<BSONObj, NamespaceString> findOneByUUID(const std::string& db,
+ UUID uuid,
+ const BSONObj& filter) const override;
+
+ void copyCollectionFromRemote(OperationContext* opCtx,
+ const NamespaceString& nss) const override;
+ StatusWith<BSONObj> getCollectionInfoByUUID(const std::string& db,
+ const UUID& uuid) const override;
+ StatusWith<BSONObj> getCollectionInfo(const NamespaceString& nss) const override;
+
+private:
+ std::unique_ptr<OplogInterface> _oplog;
+ HostAndPort _source;
+};
+
+/**
+ * Test fixture to ensure that rollback re-syncs collection options from a sync source and updates
+ * the local collection options correctly. A test operates on a single test collection, and is
+ * parameterized on two arguments:
+ *
+ * 'localCollOptions': the collection options that the local test collection is initially created
+ * with.
+ *
+ * 'remoteCollOptionsObj': the collection options object that the sync source will respond with to
+ * the rollback node when it fetches collection metadata.
+ *
+ * A collMod operation with a 'noPadding' argument is used to trigger a collection metadata resync,
+ * since the rollback of collMod operations does not take into account the actual command object. It
+ * simply re-syncs all the collection options.
+ */
+class RollbackResyncsCollectionOptionsTest : public RollbackTest {
+
+ class RollbackSourceWithCollectionOptions : public RollbackSourceMock {
+ public:
+ RollbackSourceWithCollectionOptions(std::unique_ptr<OplogInterface> oplog,
+ BSONObj collOptionsObj);
+
+ StatusWith<BSONObj> getCollectionInfo(const NamespaceString& nss) const override;
+ StatusWith<BSONObj> getCollectionInfoByUUID(const std::string& db,
+ const UUID& uuid) const override;
+
+ mutable bool calledNoUUID = false;
+ mutable bool calledWithUUID = false;
+ BSONObj collOptionsObj;
+ };
+
+public:
+ void resyncCollectionOptionsTest(CollectionOptions localCollOptions,
+ BSONObj remoteCollOptionsObj);
+};
+
} // namespace repl
} // namespace mongo
diff --git a/src/mongo/db/repl/rs_rollback_no_uuid.cpp b/src/mongo/db/repl/rs_rollback_no_uuid.cpp
index b1a633abf7e..088c28a2e7b 100644
--- a/src/mongo/db/repl/rs_rollback_no_uuid.cpp
+++ b/src/mongo/db/repl/rs_rollback_no_uuid.cpp
@@ -557,22 +557,11 @@ void syncFixUp(OperationContext* opCtx,
cce->updateFlags(opCtx, options.flags);
}
- auto status = collection->setValidator(opCtx, options.validator);
- if (!status.isOK()) {
- throw RSFatalException(str::stream() << "Failed to set validator: "
- << status.toString());
- }
- status = collection->setValidationAction(opCtx, options.validationAction);
- if (!status.isOK()) {
- throw RSFatalException(str::stream() << "Failed to set validationAction: "
- << status.toString());
- }
-
- status = collection->setValidationLevel(opCtx, options.validationLevel);
- if (!status.isOK()) {
- throw RSFatalException(str::stream() << "Failed to set validationLevel: "
- << status.toString());
- }
+ // Set any document validation options. We update the validator fields without
+ // parsing/validation, since we fetched the options object directly from the sync
+ // source, and we should set our validation options to match it exactly.
+ cce->updateValidator(
+ opCtx, options.validator, options.validationLevel, options.validationAction);
wuow.commit();
}
diff --git a/src/mongo/db/repl/rs_rollback_no_uuid_test.cpp b/src/mongo/db/repl/rs_rollback_no_uuid_test.cpp
index a08d9594033..26d918f87c2 100644
--- a/src/mongo/db/repl/rs_rollback_no_uuid_test.cpp
+++ b/src/mongo/db/repl/rs_rollback_no_uuid_test.cpp
@@ -34,6 +34,7 @@
#include <utility>
#include "mongo/db/catalog/collection.h"
+#include "mongo/db/catalog/collection_catalog_entry.h"
#include "mongo/db/catalog/drop_indexes.h"
#include "mongo/db/catalog/index_catalog.h"
#include "mongo/db/catalog/index_create.h"
@@ -64,72 +65,6 @@ using namespace mongo::repl::rollback_internal_no_uuid;
const auto kIndexVersion = IndexDescriptor::IndexVersion::kV2;
-class RollbackSourceMock : public RollbackSource {
-public:
- RollbackSourceMock(std::unique_ptr<OplogInterface> oplog);
- int getRollbackId() const override;
- const OplogInterface& getOplog() const override;
- const HostAndPort& getSource() const override;
- BSONObj getLastOperation() const override;
- BSONObj findOne(const NamespaceString& nss, const BSONObj& filter) const override;
- std::pair<BSONObj, NamespaceString> findOneByUUID(const std::string& db,
- UUID uuid,
- const BSONObj& filter) const override;
- void copyCollectionFromRemote(OperationContext* opCtx,
- const NamespaceString& nss) const override;
- StatusWith<BSONObj> getCollectionInfoByUUID(const std::string& db,
- const UUID& uuid) const override;
- StatusWith<BSONObj> getCollectionInfo(const NamespaceString& nss) const override;
-
-private:
- std::unique_ptr<OplogInterface> _oplog;
- HostAndPort _source;
-};
-
-RollbackSourceMock::RollbackSourceMock(std::unique_ptr<OplogInterface> oplog)
- : _oplog(std::move(oplog)) {}
-
-const OplogInterface& RollbackSourceMock::getOplog() const {
- return *_oplog;
-}
-
-const HostAndPort& RollbackSourceMock::getSource() const {
- return _source;
-}
-
-int RollbackSourceMock::getRollbackId() const {
- return 0;
-}
-
-BSONObj RollbackSourceMock::getLastOperation() const {
- auto iter = _oplog->makeIterator();
- auto result = iter->next();
- ASSERT_OK(result.getStatus());
- return result.getValue().first;
-}
-
-BSONObj RollbackSourceMock::findOne(const NamespaceString& nss, const BSONObj& filter) const {
- return BSONObj();
-}
-
-std::pair<BSONObj, NamespaceString> RollbackSourceMock::findOneByUUID(const std::string& db,
- UUID uuid,
- const BSONObj& filter) const {
- return {BSONObj(), NamespaceString()};
-}
-
-void RollbackSourceMock::copyCollectionFromRemote(OperationContext* opCtx,
- const NamespaceString& nss) const {}
-
-StatusWith<BSONObj> RollbackSourceMock::getCollectionInfoByUUID(const std::string& db,
- const UUID& uuid) const {
- return BSON("options" << BSONObj() << "info" << BSON("uuid" << uuid));
-}
-
-StatusWith<BSONObj> RollbackSourceMock::getCollectionInfo(const NamespaceString& nss) const {
- return BSON("name" << nss.ns() << "options" << BSONObj());
-}
-
class RSRollbackTest : public RollbackTest {
private:
void setUp() override;
@@ -260,30 +195,6 @@ TEST_F(RSRollbackTest, BothOplogsAtCommonPoint) {
}
/**
- * Create test collection.
- * Returns collection.
- */
-Collection* _createCollection(OperationContext* opCtx,
- const NamespaceString& nss,
- const CollectionOptions& options) {
- Lock::DBLock dbLock(opCtx, nss.db(), MODE_X);
- mongo::WriteUnitOfWork wuow(opCtx);
- auto db = dbHolder().openDb(opCtx, nss.db());
- ASSERT_TRUE(db);
- db->dropCollection(opCtx, nss.ns()).transitional_ignore();
- auto coll = db->createCollection(opCtx, nss.ns(), options);
- ASSERT_TRUE(coll);
- wuow.commit();
- return coll;
-}
-
-Collection* _createCollection(OperationContext* opCtx,
- const std::string& nss,
- const CollectionOptions& options) {
- return _createCollection(opCtx, NamespaceString(nss), options);
-}
-
-/**
* Test function to roll back a delete operation.
* Returns number of records in collection after rolling back delete operation.
* If collection does not exist after rolling back, returns -1.
@@ -1153,26 +1064,24 @@ TEST_F(RSRollbackTest, RollbackCreateCollectionCommand) {
TEST_F(RSRollbackTest, RollbackCollectionModificationCommand) {
createOplog(_opCtx.get());
+ _createCollection(_opCtx.get(), "test.t", CollectionOptions());
auto commonOperation =
std::make_pair(BSON("ts" << Timestamp(Seconds(1), 0) << "h" << 1LL), RecordId(1));
+ BSONObj collModCmd = BSON("collMod"
+ << "t"
+ << "noPadding"
+ << false);
auto collectionModificationOperation =
- std::make_pair(BSON("ts" << Timestamp(Seconds(2), 0) << "h" << 1LL << "op"
- << "c"
- << "ns"
- << "test.t"
- << "o"
- << BSON("collMod"
- << "t"
- << "noPadding"
- << false)),
- RecordId(2));
+ makeCommandOp(Timestamp(Seconds(2), 0), boost::none, "test.t", collModCmd, 2);
class RollbackSourceLocal : public RollbackSourceMock {
public:
RollbackSourceLocal(std::unique_ptr<OplogInterface> oplog)
: RollbackSourceMock(std::move(oplog)), called(false) {}
+
+ // Remote collection options are empty.
StatusWith<BSONObj> getCollectionInfo(const NamespaceString& nss) const {
called = true;
- return RollbackSourceMock::getCollectionInfo(nss);
+ return BSON("options" << BSONObj());
}
mutable bool called;
};
@@ -1194,6 +1103,76 @@ TEST_F(RSRollbackTest, RollbackCollectionModificationCommand) {
ASSERT_TRUE(message.find("ignoring op with no _id during rollback. ns: test.t") ==
std::string::npos);
}
+
+ // Make sure the collection options are correct.
+ AutoGetCollectionForReadCommand autoColl(_opCtx.get(), NamespaceString("test.t"));
+ auto collAfterRollbackOptions =
+ autoColl.getCollection()->getCatalogEntry()->getCollectionOptions(_opCtx.get());
+ ASSERT(collAfterRollbackOptions.toBSON().isEmpty());
+}
+
+TEST_F(RollbackResyncsCollectionOptionsTest,
+ FullRemoteCollectionValidationOptionsAndEmptyLocalValidationOptions) {
+ // Empty local collection options.
+ CollectionOptions localCollOptions;
+
+ // Full remote collection validation options.
+ BSONObj remoteCollOptionsObj =
+ BSON("validator" << BSON("x" << BSON("$exists" << 1)) << "validationLevel"
+ << "moderate"
+ << "validationAction"
+ << "warn");
+
+ resyncCollectionOptionsTest(localCollOptions, remoteCollOptionsObj);
+}
+
+TEST_F(RollbackResyncsCollectionOptionsTest,
+ PartialRemoteCollectionValidationOptionsAndEmptyLocalValidationOptions) {
+ CollectionOptions localCollOptions;
+
+ BSONObj remoteCollOptionsObj = BSON("validationLevel"
+ << "moderate"
+ << "validationAction"
+ << "warn");
+
+ resyncCollectionOptionsTest(localCollOptions, remoteCollOptionsObj);
+}
+
+TEST_F(RollbackResyncsCollectionOptionsTest,
+ PartialRemoteCollectionValidationOptionsAndFullLocalValidationOptions) {
+ CollectionOptions localCollOptions;
+ localCollOptions.validator = BSON("x" << BSON("$exists" << 1));
+ localCollOptions.validationLevel = "moderate";
+ localCollOptions.validationAction = "warn";
+
+ BSONObj remoteCollOptionsObj = BSON("validationLevel"
+ << "strict"
+ << "validationAction"
+ << "error");
+
+
+ resyncCollectionOptionsTest(localCollOptions, remoteCollOptionsObj);
+}
+
+TEST_F(RollbackResyncsCollectionOptionsTest,
+ EmptyRemoteCollectionValidationOptionsAndEmptyLocalValidationOptions) {
+ CollectionOptions localCollOptions;
+
+ BSONObj remoteCollOptionsObj = BSONObj();
+
+ resyncCollectionOptionsTest(localCollOptions, remoteCollOptionsObj);
+}
+
+TEST_F(RollbackResyncsCollectionOptionsTest,
+ EmptyRemoteCollectionValidationOptionsAndFullLocalValidationOptions) {
+ CollectionOptions localCollOptions;
+ localCollOptions.validator = BSON("x" << BSON("$exists" << 1));
+ localCollOptions.validationLevel = "moderate";
+ localCollOptions.validationAction = "warn";
+
+ BSONObj remoteCollOptionsObj = BSONObj();
+
+ resyncCollectionOptionsTest(localCollOptions, remoteCollOptionsObj);
}
TEST_F(RSRollbackTest, RollbackCollectionModificationCommandInvalidCollectionOptions) {
diff --git a/src/mongo/db/repl/rs_rollback_test.cpp b/src/mongo/db/repl/rs_rollback_test.cpp
index 6e93453ea1c..4b656e2e61e 100644
--- a/src/mongo/db/repl/rs_rollback_test.cpp
+++ b/src/mongo/db/repl/rs_rollback_test.cpp
@@ -67,75 +67,6 @@ using namespace mongo::repl::rollback_internal;
const auto kIndexVersion = IndexDescriptor::IndexVersion::kV2;
-class RollbackSourceMock : public RollbackSource {
-public:
- RollbackSourceMock(std::unique_ptr<OplogInterface> oplog);
- int getRollbackId() const override;
- const OplogInterface& getOplog() const override;
- const HostAndPort& getSource() const override;
- BSONObj getLastOperation() const override;
- BSONObj findOne(const NamespaceString& nss, const BSONObj& filter) const override;
-
- std::pair<BSONObj, NamespaceString> findOneByUUID(const std::string& db,
- UUID uuid,
- const BSONObj& filter) const override;
-
- void copyCollectionFromRemote(OperationContext* opCtx,
- const NamespaceString& nss) const override;
- StatusWith<BSONObj> getCollectionInfoByUUID(const std::string& db,
- const UUID& uuid) const override;
- StatusWith<BSONObj> getCollectionInfo(const NamespaceString& nss) const override;
-
-private:
- std::unique_ptr<OplogInterface> _oplog;
- HostAndPort _source;
-};
-
-RollbackSourceMock::RollbackSourceMock(std::unique_ptr<OplogInterface> oplog)
- : _oplog(std::move(oplog)) {}
-
-const OplogInterface& RollbackSourceMock::getOplog() const {
- return *_oplog;
-}
-
-const HostAndPort& RollbackSourceMock::getSource() const {
- return _source;
-}
-
-int RollbackSourceMock::getRollbackId() const {
- return 0;
-}
-
-BSONObj RollbackSourceMock::getLastOperation() const {
- auto iter = _oplog->makeIterator();
- auto result = iter->next();
- ASSERT_OK(result.getStatus());
- return result.getValue().first;
-}
-
-BSONObj RollbackSourceMock::findOne(const NamespaceString& nss, const BSONObj& filter) const {
- return BSONObj();
-}
-
-std::pair<BSONObj, NamespaceString> RollbackSourceMock::findOneByUUID(const std::string& db,
- UUID uuid,
- const BSONObj& filter) const {
- return {BSONObj(), NamespaceString()};
-}
-
-void RollbackSourceMock::copyCollectionFromRemote(OperationContext* opCtx,
- const NamespaceString& nss) const {}
-
-StatusWith<BSONObj> RollbackSourceMock::getCollectionInfo(const NamespaceString& nss) const {
- return BSON("name" << nss.ns() << "options" << BSONObj());
-}
-
-StatusWith<BSONObj> RollbackSourceMock::getCollectionInfoByUUID(const std::string& db,
- const UUID& uuid) const {
- return BSON("options" << BSONObj() << "info" << BSON("uuid" << uuid));
-}
-
-
class RSRollbackTest : public RollbackTest {
private:
void setUp() override;
@@ -357,30 +288,6 @@ TEST_F(RSRollbackTest, BothOplogsAtCommonPoint) {
}
/**
- * Create test collection.
- * Returns collection.
- */
-Collection* _createCollection(OperationContext* opCtx,
- const NamespaceString& nss,
- const CollectionOptions& options) {
- Lock::DBLock dbLock(opCtx, nss.db(), MODE_X);
- mongo::WriteUnitOfWork wuow(opCtx);
- auto db = dbHolder().openDb(opCtx, nss.db());
- ASSERT_TRUE(db);
- db->dropCollection(opCtx, nss.ns()).transitional_ignore();
- auto coll = db->createCollection(opCtx, nss.ns(), options);
- ASSERT_TRUE(coll);
- wuow.commit();
- return coll;
-}
-
-Collection* _createCollection(OperationContext* opCtx,
- const std::string& nss,
- const CollectionOptions& options) {
- return _createCollection(opCtx, NamespaceString(nss), options);
-}
-
-/**
* Test function to roll back a delete operation.
* Returns number of records in collection after rolling back delete operation.
* If collection does not exist after rolling back, returns -1.
@@ -1275,10 +1182,10 @@ void _testRollbackRenamingCollectionsToEachOther(OperationContext* opCtx,
const CollectionOptions& coll2Options) {
createOplog(opCtx);
- auto collection1 = _createCollection(opCtx, "test.y", coll1Options);
+ auto collection1 = RollbackTest::_createCollection(opCtx, "test.y", coll1Options);
auto collection1UUID = collection1->uuid().get();
- auto collection2 = _createCollection(opCtx, "test.x", coll2Options);
+ auto collection2 = RollbackTest::_createCollection(opCtx, "test.x", coll2Options);
auto collection2UUID = collection2->uuid().get();
ASSERT_NOT_EQUALS(collection1UUID, collection2UUID);
@@ -1824,22 +1731,6 @@ TEST_F(RSRollbackTest, RollbackCreateCollectionCommand) {
}
}
-std::pair<BSONObj, RecordId> makeCommandOp(
- Timestamp ts, OptionalCollectionUUID uuid, StringData nss, BSONObj cmdObj, int recordId) {
-
- BSONObjBuilder bob;
- bob.append("ts", ts);
- bob.append("h", 1LL);
- bob.append("op", "c");
- if (uuid) { // Not all ops have UUID fields.
- uuid.get().appendToBuilder(&bob, "ui");
- }
- bob.append("ns", nss);
- bob.append("o", cmdObj);
-
- return std::make_pair(bob.obj(), RecordId(recordId));
-}
-
TEST_F(RSRollbackTest, RollbackCollectionModificationCommand) {
createOplog(_opCtx.get());
CollectionOptions options;
@@ -1893,84 +1784,6 @@ TEST_F(RSRollbackTest, RollbackCollectionModificationCommand) {
ASSERT_BSONOBJ_EQ(BSON("uuid" << *options.uuid), collAfterRollbackOptions.toBSON());
}
-/**
- * Test fixture to ensure that rollback re-syncs collection options from a sync source and updates
- * the local collection options correctly. A test operates on a single test collection, with a fixed
- * UUID, and is parameterized on two arguments:
- *
- * 'localCollOptions': the collection options that the local test collection is initially created
- * with.
- *
- * 'remoteCollOptionsObj': the collection options object that the sync source will respond with to
- * the rollback node when it fetches collection metadata.
- *
- * A collMod operation with a 'noPadding' argument is used to trigger a collection metadata resync,
- * since the rollback of collMod operations does not take into account the actual command object. It
- * simply re-syncs all the collection options.
- */
-class RollbackResyncsCollectionOptionsTest : public RollbackTest {
-
-
- class RollbackSourceWithCollectionOptions : public RollbackSourceMock {
- public:
- RollbackSourceWithCollectionOptions(std::unique_ptr<OplogInterface> oplog,
- BSONObj collOptionsObj)
- : RollbackSourceMock(std::move(oplog)), collOptionsObj(collOptionsObj) {}
-
- StatusWith<BSONObj> getCollectionInfoByUUID(const std::string& db, const UUID& uuid) const {
- called = true;
- return BSON("options" << collOptionsObj << "info" << BSON("uuid" << uuid));
- }
-
- mutable bool called = false;
- BSONObj collOptionsObj;
- };
-
-public:
- void resyncCollectionOptionsTest(CollectionOptions localCollOptions,
- BSONObj remoteCollOptionsObj) {
- createOplog(_opCtx.get());
-
- auto dbName = "test";
- auto collName = "coll";
- auto nss = NamespaceString(dbName, collName);
-
- auto coll = _createCollection(_opCtx.get(), nss.toString(), localCollOptions);
- auto commonOperation =
- std::make_pair(BSON("ts" << Timestamp(Seconds(1), 0) << "h" << 1LL), RecordId(1));
-
- // 'collMod' operation used to trigger metadata re-sync.
- BSONObj collModCmd = BSON("collMod" << collName << "noPadding" << false);
- auto collectionModificationOperation = makeCommandOp(
- Timestamp(Seconds(2), 0), coll->uuid().get(), nss.toString(), collModCmd, 2);
-
- RollbackSourceWithCollectionOptions rollbackSource(
- std::unique_ptr<OplogInterface>(new OplogInterfaceMock({commonOperation})),
- remoteCollOptionsObj);
-
- ASSERT_OK(
- syncRollback(_opCtx.get(),
- OplogInterfaceMock({collectionModificationOperation, commonOperation}),
- rollbackSource,
- {},
- _coordinator,
- _replicationProcess.get()));
-
- ASSERT_TRUE(rollbackSource.called);
-
- // Make sure the collection options are correct.
- AutoGetCollectionForReadCommand autoColl(_opCtx.get(), NamespaceString(nss.toString()));
- auto collAfterRollbackOptions =
- autoColl.getCollection()->getCatalogEntry()->getCollectionOptions(_opCtx.get());
-
- BSONObjBuilder expectedOptionsBob;
- localCollOptions.uuid.get().appendToBuilder(&expectedOptionsBob, "uuid");
- expectedOptionsBob.appendElements(remoteCollOptionsObj);
-
- ASSERT_BSONOBJ_EQ(expectedOptionsBob.obj(), collAfterRollbackOptions.toBSON());
- }
-};
-
TEST_F(RollbackResyncsCollectionOptionsTest,
FullRemoteCollectionValidationOptionsAndEmptyLocalValidationOptions) {
// Empty local collection options.