diff options
author | Matthew Russotto <matthew.russotto@10gen.com> | 2020-05-12 10:20:53 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-05-12 14:39:35 +0000 |
commit | f9f1d128ea2b4f531f3e9a92027369ebef3507fa (patch) | |
tree | 7c34195a95df2ce8c397fecd0375f0c34f96aa7a | |
parent | 4423364192774ed484dedd943a0bd1f04fd84e41 (diff) | |
download | mongo-f9f1d128ea2b4f531f3e9a92027369ebef3507fa.tar.gz |
SERVER-47091 Make ReplSetConfig and MemberConfig immutable
25 files changed, 1825 insertions, 1739 deletions
diff --git a/jstests/replsets/remove_newly_added_field_after_finishing_initial_sync.js b/jstests/replsets/remove_newly_added_field_after_finishing_initial_sync.js index 4d333cbd189..82a95d45c7e 100644 --- a/jstests/replsets/remove_newly_added_field_after_finishing_initial_sync.js +++ b/jstests/replsets/remove_newly_added_field_after_finishing_initial_sync.js @@ -216,8 +216,7 @@ assert.commandWorked(primaryColl.insert({"steady": "state"}, {writeConcern: {w: // is) can be one of them (0, 1, and 3). rst.nodes[2].disconnect(rst.nodes); -// TODO (SERVER-47499): Uncomment this line. -// assert.commandWorked(primaryColl.insert({a: 8}, {writeConcern: {w: "majority"}})); +assert.commandWorked(primaryColl.insert({a: 8}, {writeConcern: {w: "majority"}})); // Only three nodes are needed for an election (0, 1, and 3). assert.commandWorked(rst.nodes[1].adminCommand({replSetStepUp: 1})); @@ -245,4 +244,4 @@ rst.nodes[2].reconnect(rst.nodes); rst.nodes[3].reconnect(rst.nodes); rst.stopSet(); -})();
\ No newline at end of file +})(); diff --git a/src/mongo/client/dbclient_rs_test.cpp b/src/mongo/client/dbclient_rs_test.cpp index 06279c2d991..93e9fdeea06 100644 --- a/src/mongo/client/dbclient_rs_test.cpp +++ b/src/mongo/client/dbclient_rs_test.cpp @@ -653,8 +653,7 @@ protected: } membersBuilder.done(); - mongo::repl::ReplSetConfig newConfig; - fassert(28569, newConfig.initialize(newConfigBuilder.done())); + auto newConfig = mongo::repl::ReplSetConfig::parse(newConfigBuilder.done()); fassert(28568, newConfig.validate()); _replSet->setConfig(newConfig); } diff --git a/src/mongo/db/repl/check_quorum_for_config_change_test.cpp b/src/mongo/db/repl/check_quorum_for_config_change_test.cpp index 0264f7cec99..13b8f420670 100644 --- a/src/mongo/db/repl/check_quorum_for_config_change_test.cpp +++ b/src/mongo/db/repl/check_quorum_for_config_change_test.cpp @@ -134,8 +134,7 @@ protected: }; ReplSetConfig assertMakeRSConfig(const BSONObj& configBson) { - ReplSetConfig config; - ASSERT_OK(config.initialize(configBson)); + ReplSetConfig config(ReplSetConfig::parse(configBson)); ASSERT_OK(config.validate()); return config; } diff --git a/src/mongo/db/repl/initial_syncer_test.cpp b/src/mongo/db/repl/initial_syncer_test.cpp index a3e107bda50..489b885784c 100644 --- a/src/mongo/db/repl/initial_syncer_test.cpp +++ b/src/mongo/db/repl/initial_syncer_test.cpp @@ -400,14 +400,14 @@ protected: dataReplicatorExternalState->currentTerm = 1LL; dataReplicatorExternalState->lastCommittedOpTime = _myLastOpTime; { - ReplSetConfig config; - ASSERT_OK( - config.initialize(BSON("_id" - << "myset" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" << BSON("electionTimeoutMillis" << 10000)))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "myset" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" + << BSON("electionTimeoutMillis" << 10000)))); dataReplicatorExternalState->replSetConfigResult = config; } _externalState = dataReplicatorExternalState.get(); diff --git a/src/mongo/db/repl/member_config.cpp b/src/mongo/db/repl/member_config.cpp index aec6ae71762..1cf7caf176d 100644 --- a/src/mongo/db/repl/member_config.cpp +++ b/src/mongo/db/repl/member_config.cpp @@ -116,6 +116,10 @@ MemberConfig::MemberConfig(const BSONObj& mcfg, ReplSetTagConfig* tagConfig) : M } void MemberConfig::addTagInfo(ReplSetTagConfig* tagConfig) { + // When a ReplSetConfig is created from a MutableReplSetConfig, the MemberConfig objects + // may have tags from the original configuration, so we need to clear them before adding + // the tags from the modified configuration. + _tags.clear(); // // Parse "tags" field. // @@ -172,6 +176,28 @@ bool MemberConfig::hasTags() const { return getTags() && !getTags()->isEmpty(); } +// Changing these members may change the tags, so invalidate them. The tags will be rebuilt +// when addTagInfo is called. +void MemberConfig::setNewlyAdded(boost::optional<bool> newlyAdded) { + _tags.clear(); + MemberConfigBase::setNewlyAdded(newlyAdded); +} + +void MemberConfig::setArbiterOnly(bool arbiterOnly) { + _tags.clear(); + MemberConfigBase::setArbiterOnly(arbiterOnly); +} + +void MemberConfig::setVotes(int64_t votes) { + _tags.clear(); + MemberConfigBase::setVotes(votes); +} + +void MemberConfig::setPriority(double priority) { + _tags.clear(); + MemberConfigBase::setPriority(priority); +} + BSONObj MemberConfig::toBSON(bool omitNewlyAddedField) const { BSONObjBuilder configBuilder; configBuilder.append(kIdFieldName, getId().getData()); diff --git a/src/mongo/db/repl/member_config.h b/src/mongo/db/repl/member_config.h index 9b9c3abee16..d6bb75622f3 100644 --- a/src/mongo/db/repl/member_config.h +++ b/src/mongo/db/repl/member_config.h @@ -54,7 +54,6 @@ class MemberConfig : private MemberConfigBase { public: // Expose certain member functions used externally. using MemberConfigBase::getId; - using MemberConfigBase::setNewlyAdded; using MemberConfigBase::kArbiterOnlyFieldName; using MemberConfigBase::kBuildIndexesFieldName; @@ -191,6 +190,10 @@ public: * Gets the number of replica set tags, including internal '$' tags, for this member. */ size_t getNumTags() const { + // All valid MemberConfig objects should have at least one tag, kInternalAllTagName if + // nothing else. So if we're accessing an empty _tags array we're using a MemberConfig + // from a MutableReplSetConfig, which is invalid. + invariant(!_tags.empty()); return _tags.size(); } @@ -203,6 +206,7 @@ public: * Gets a begin iterator over the tags for this member. */ TagIterator tagsBegin() const { + invariant(!_tags.empty()); return _tags.begin(); } @@ -210,6 +214,7 @@ public: * Gets an end iterator over the tags for this member. */ TagIterator tagsEnd() const { + invariant(!_tags.empty()); return _tags.end(); } @@ -231,6 +236,11 @@ public: void addTagInfo(ReplSetTagConfig* tagConfig); private: + // Allow MutableReplSetConfig to modify the newlyAdded field. + friend class MutableReplSetConfig; + + friend void setNewlyAdded_ForTest(MemberConfig*, boost::optional<bool>); + /** * Constructor used by IDL; does not set up tags because we cannot pass TagConfig through IDL. */ @@ -240,6 +250,16 @@ private: return getHostAndPort(SplitHorizon::kDefaultHorizon); } + /** + * Modifiers which potentially affect tags. Calling them clears the tags array, which + * will be rebuilt when addTagInfo is called. Accessing a cleared tags array is not allowed + * and is enforced by invariant. + */ + void setNewlyAdded(boost::optional<bool> newlyAdded); + void setArbiterOnly(bool arbiterOnly); + void setVotes(int64_t votes); + void setPriority(double priority); + std::vector<ReplSetTag> _tags; // tagging for data center, rack, etc. SplitHorizon _splitHorizon; }; diff --git a/src/mongo/db/repl/member_config_test.cpp b/src/mongo/db/repl/member_config_test.cpp index 1fbfb94329b..04037567886 100644 --- a/src/mongo/db/repl/member_config_test.cpp +++ b/src/mongo/db/repl/member_config_test.cpp @@ -213,7 +213,13 @@ TEST(MemberConfig, ParseArbiterOnly) { ASSERT_EQUALS(1.0, mc.getPriority()); } } +} // namespace + +void setNewlyAdded_ForTest(MemberConfig* mc, boost::optional<bool> newlyAdded) { + mc->setNewlyAdded(newlyAdded); +} +namespace { TEST(MemberConfig, ParseAndSetNewlyAddedField) { // Set the flag to add the 'newlyAdded' field to MemberConfigs. enableAutomaticReconfig = true; @@ -228,7 +234,7 @@ TEST(MemberConfig, ParseAndSetNewlyAddedField) { // Verify that the 'newlyAdded' field is not added by default. ASSERT_FALSE(mc.isNewlyAdded()); - mc.setNewlyAdded(true); + setNewlyAdded_ForTest(&mc, true); ASSERT_TRUE(mc.isNewlyAdded()); } { diff --git a/src/mongo/db/repl/oplog_fetcher_test.cpp b/src/mongo/db/repl/oplog_fetcher_test.cpp index 2167459de47..170e506a5d6 100644 --- a/src/mongo/db/repl/oplog_fetcher_test.cpp +++ b/src/mongo/db/repl/oplog_fetcher_test.cpp @@ -72,8 +72,7 @@ ReplSetConfig _createConfig() { } auto configObj = bob.obj(); - ReplSetConfig config; - ASSERT_OK(config.initialize(configObj)); + ReplSetConfig config(ReplSetConfig::parse(configObj)); return config; } diff --git a/src/mongo/db/repl/repl_set_config.cpp b/src/mongo/db/repl/repl_set_config.cpp index c9c2ea06796..02ea0d4cb1d 100644 --- a/src/mongo/db/repl/repl_set_config.cpp +++ b/src/mongo/db/repl/repl_set_config.cpp @@ -27,6 +27,8 @@ * it in the license file. */ +#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kReplication + #include "mongo/platform/basic.h" #include "mongo/db/repl/repl_set_config.h" @@ -39,6 +41,7 @@ #include "mongo/db/jsobj.h" #include "mongo/db/mongod_options.h" #include "mongo/db/server_options.h" +#include "mongo/logv2/log.h" #include "mongo/util/str.h" namespace mongo { @@ -64,28 +67,27 @@ namespace { const std::string kStepDownCheckWriteConcernModeName = "$stepDownCheck"; } // namespace -Status ReplSetConfig::initialize(const BSONObj& cfg, - boost::optional<long long> forceTerm, - OID defaultReplicaSetId) { - return _initialize(cfg, false, forceTerm, defaultReplicaSetId); +/* static */ +ReplSetConfig ReplSetConfig::parse(const BSONObj& cfg, + boost::optional<long long> forceTerm, + OID defaultReplicaSetId) { + return ReplSetConfig(cfg, false /* forInitiate */, forceTerm, defaultReplicaSetId); } -Status ReplSetConfig::initializeForInitiate(const BSONObj& cfg, OID newReplicaSetId) { - if (!newReplicaSetId.isSet()) { - return Status(ErrorCodes::Error(4709000), - "A replica set ID must be provided to initializeForInitiate"); - } - - auto status = _initialize(cfg, true, OpTime::kInitialTerm, newReplicaSetId); - if (status.isOK() && newReplicaSetId != getReplicaSetId()) { - return Status(ErrorCodes::InvalidReplicaSetConfig, - str::stream() << "replica set configuration cannot contain '" - << ReplSetConfigSettings::kReplicaSetIdFieldName - << "' " - "field when called from replSetInitiate: " - << cfg); - } - return status; +/* static */ +ReplSetConfig ReplSetConfig::parseForInitiate(const BSONObj& cfg, OID newReplicaSetId) { + uassert( + 4709000, "A replica set ID must be provided to parseForInitiate", newReplicaSetId.isSet()); + auto result = ReplSetConfig( + cfg, true /* forInitiate */, OpTime::kInitialTerm /* forceTerm*/, newReplicaSetId); + uassert(ErrorCodes::InvalidReplicaSetConfig, + str::stream() << "replica set configuration cannot contain '" + << ReplSetConfigSettings::kReplicaSetIdFieldName + << "' " + "field when called from replSetInitiate: " + << cfg, + newReplicaSetId == result.getReplicaSetId()); + return result; } void ReplSetConfig::_setRequiredFields() { @@ -99,23 +101,26 @@ void ReplSetConfig::_setRequiredFields() { setMembers({}); } -Status ReplSetConfig::_initialize(const BSONObj& cfg, - bool forInitiate, - boost::optional<long long> forceTerm, - OID defaultReplicaSetId) { - _isInitialized = false; - // This line clears the base IDL class, and is necessary because an object may be re-used. - *static_cast<ReplSetConfigBase*>(this) = ReplSetConfigBase(); +ReplSetConfig::ReplSetConfig(MutableReplSetConfig&& base) + : MutableReplSetConfig(std::move(base)), _isInitialized(true) { + uassertStatusOK(_initialize(false, boost::none, OID())); +} + +ReplSetConfig::ReplSetConfig(const BSONObj& cfg, + bool forInitiate, + boost::optional<long long> forceTerm, + OID defaultReplicaSetId) + : _isInitialized(true) { // The settings field is optional, but we always serialize it. Because we can't default it in // the IDL, we default it here. setSettings(ReplSetConfigSettings()); - try { - ReplSetConfigBase::parseProtected(IDLParserErrorContext("ReplSetConfig"), cfg); - } catch (const DBException& e) { - _setRequiredFields(); - return e.toStatus(); - } + ReplSetConfigBase::parseProtected(IDLParserErrorContext("ReplSetConfig"), cfg); + uassertStatusOK(_initialize(forInitiate, forceTerm, defaultReplicaSetId)); +} +Status ReplSetConfig::_initialize(bool forInitiate, + boost::optional<long long> forceTerm, + OID defaultReplicaSetId) { if (getRepaired()) { return {ErrorCodes::RepairedReplicaSetNode, "Replicated data has been repaired"}; } @@ -160,7 +165,6 @@ Status ReplSetConfig::_initialize(const BSONObj& cfg, _calculateMajorities(); _addInternalWriteConcernModes(); _initializeConnectionString(); - _isInitialized = true; return Status::OK(); } @@ -437,15 +441,6 @@ const MemberConfig* ReplSetConfig::findMemberByID(int id) const { return nullptr; } -MemberConfig* ReplSetConfig::_findMemberByID(MemberId id) { - for (auto it = getMembers().begin(); it != getMembers().end(); ++it) { - if (it->getId() == id) { - return const_cast<MemberConfig*>(&(*it)); - } - } - return nullptr; -} - int ReplSetConfig::findMemberIndexByHostAndPort(const HostAndPort& hap) const { int x = 0; for (std::vector<MemberConfig>::const_iterator it = getMembers().begin(); @@ -656,22 +651,25 @@ bool ReplSetConfig::containsArbiter() const { return false; } -void ReplSetConfig::addNewlyAddedFieldForMember(MemberId memberId) { - _findMemberByID(memberId)->setNewlyAdded(true); +MutableReplSetConfig ReplSetConfig::getMutable() const { + return *static_cast<const MutableReplSetConfig*>(this); +} - // We must recalculate the majority, since nodes with the 'newlyAdded' field set - // should be treated as non-voting nodes. - _calculateMajorities(); - _addInternalWriteConcernModes(); +MemberConfig* MutableReplSetConfig::_findMemberByID(MemberId id) { + for (auto it = getMembers().begin(); it != getMembers().end(); ++it) { + if (it->getId() == id) { + return const_cast<MemberConfig*>(&(*it)); + } + } + LOGV2_FATAL(4709100, "Unable to find member", "id"_attr = id); } -void ReplSetConfig::removeNewlyAddedFieldForMember(MemberId memberId) { - _findMemberByID(memberId)->setNewlyAdded(boost::none); +void MutableReplSetConfig::addNewlyAddedFieldForMember(MemberId memberId) { + _findMemberByID(memberId)->setNewlyAdded(true); +} - // We must recalculate the majority, since nodes with the 'newlyAdded' field removed - // should be treated as voting nodes. - _calculateMajorities(); - _addInternalWriteConcernModes(); +void MutableReplSetConfig::removeNewlyAddedFieldForMember(MemberId memberId) { + _findMemberByID(memberId)->setNewlyAdded(boost::none); } } // namespace repl diff --git a/src/mongo/db/repl/repl_set_config.h b/src/mongo/db/repl/repl_set_config.h index 694509a7624..a3ac31fb58b 100644 --- a/src/mongo/db/repl/repl_set_config.h +++ b/src/mongo/db/repl/repl_set_config.h @@ -109,9 +109,41 @@ private: }; /** + * This class is used for mutating the ReplicaSetConfig. Call ReplSetConfig::getMutable() + * to get a mutable copy, mutate it, and use the ReplSetConfig(MutableReplSetConfig&&) constructor + * to get a usable immutable config from it. + */ +class MutableReplSetConfig : public ReplSetConfigBase { +public: + ReplSetConfigSettings& getMutableSettings() { + invariant(ReplSetConfigBase::getSettings()); + // TODO(SERVER-47937): Get rid of the const_cast when the IDL supports that. + return const_cast<ReplSetConfigSettings&>(*ReplSetConfigBase::getSettings()); + } + + /** + * Adds 'newlyAdded=true' to the MemberConfig of the specified member. + */ + void addNewlyAddedFieldForMember(MemberId memberId); + + /** + * Removes the 'newlyAdded' field from the MemberConfig of the specified member. + */ + void removeNewlyAddedFieldForMember(MemberId memberId); + +protected: + MutableReplSetConfig() = default; + + /** + * Returns a pointer to a mutable MemberConfig. + */ + MemberConfig* _findMemberByID(MemberId id); +}; + +/** * Representation of the configuration information about a particular replica set. */ -class ReplSetConfig : private ReplSetConfigBase { +class ReplSetConfig : private MutableReplSetConfig { public: typedef std::vector<MemberConfig>::const_iterator MemberIterator; @@ -143,44 +175,46 @@ public: static const bool kDefaultChainingAllowed; static const Milliseconds kDefaultCatchUpTakeoverDelay; - // Methods inherited from the base IDL class. - using ReplSetConfigBase::getConfigVersion; - using ReplSetConfigBase::setConfigVersion; - + // Methods inherited from the base IDL class. Do not include any setters here. + using ReplSetConfigBase::getConfigServer; using ReplSetConfigBase::getConfigTerm; - using ReplSetConfigBase::setConfigTerm; - + using ReplSetConfigBase::getConfigVersion; using ReplSetConfigBase::getProtocolVersion; - - using ReplSetConfigBase::getWriteConcernMajorityShouldJournal; - - using ReplSetConfigBase::getConfigServer; using ReplSetConfigBase::getReplSetName; - + using ReplSetConfigBase::getWriteConcernMajorityShouldJournal; using ReplSetConfigBase::toBSON; + /** + * Constructor used for converting a mutable config to an immutable one. + */ + explicit ReplSetConfig(MutableReplSetConfig&& base); + ReplSetConfig() { // This is not defaultable in the IDL. + // SERVER-47938 would make it possible to be defaulted. + setSettings(ReplSetConfigSettings()); _setRequiredFields(); } /** - * Initializes this ReplSetConfig from the contents of "cfg". + * Initializes a new ReplSetConfig from the contents of "cfg". * Sets replicaSetId to "defaultReplicaSetId" if a replica set ID is not specified in "cfg"; * If forceTerm is not boost::none, sets _term to the given term. Otherwise, uses term from * config BSON. + * + * Parse errors are reported via exceptions. */ - Status initialize(const BSONObj& cfg, - boost::optional<long long> forceTerm = boost::none, - OID defaultReplicaSetId = OID()); + static ReplSetConfig parse(const BSONObj& cfg, + boost::optional<long long> forceTerm = boost::none, + OID defaultReplicaSetId = OID()); /** - * Same as the generic initialize() above except will default "configsvr" setting to the value + * Same as the generic parse() above except will default "configsvr" setting to the value * of serverGlobalParams.configsvr. * Sets term to kInitialTerm. * Sets replicaSetId to "newReplicaSetId", which must be set. */ - Status initializeForInitiate(const BSONObj& cfg, OID newReplicaSetId); + static ReplSetConfig parseForInitiate(const BSONObj& cfg, OID newReplicaSetId); /** * Returns true if this object has been successfully initialized or copied from @@ -452,16 +486,21 @@ public: bool containsArbiter() const; /** - * Adds 'newlyAdded=true' to the MemberConfig of the specified member. + * Returns a mutable (but not directly usable) copy of the config. */ - void addNewlyAddedFieldForMember(MemberId memberId); + MutableReplSetConfig getMutable() const; +private: /** - * Removes the 'newlyAdded' field from the MemberConfig of the specified member. + * Sets replica set ID to 'defaultReplicaSetId' if 'cfg' does not contain an ID. + * Sets term to kInitialTerm for initiate. + * Sets term to forceTerm if it is not boost::none. Otherwise, parses term from 'cfg'. */ - void removeNewlyAddedFieldForMember(MemberId memberId); + ReplSetConfig(const BSONObj& cfg, + bool forInitiate, + boost::optional<long long> forceTerm, + OID defaultReplicaSetId); -private: /** * Calculates and stores the majority for electing a primary (_majorityVoteCount). */ @@ -483,17 +522,9 @@ private: void _setRequiredFields(); /** - * Returns a pointer to a mutable MemberConfig. - */ - MemberConfig* _findMemberByID(MemberId id); - - /** - * Sets replica set ID to 'defaultReplicaSetId' if 'cfg' does not contain an ID. - * Sets term to kInitialTerm for initiate. - * Sets term to forceTerm if it is not boost::none. Otherwise, parses term from 'cfg'. + * Common code used by constructors */ - Status _initialize(const BSONObj& cfg, - bool forInitiate, + Status _initialize(bool forInitiate, boost::optional<long long> forceTerm, OID defaultReplicaSetId); @@ -507,6 +538,5 @@ private: ConnectionString _connectionString; }; - } // namespace repl } // namespace mongo diff --git a/src/mongo/db/repl/repl_set_config_checks_test.cpp b/src/mongo/db/repl/repl_set_config_checks_test.cpp index 797ee7fb377..6aa169249d4 100644 --- a/src/mongo/db/repl/repl_set_config_checks_test.cpp +++ b/src/mongo/db/repl/repl_set_config_checks_test.cpp @@ -55,13 +55,13 @@ TEST_F(ServiceContextTest, ValidateConfigForInitiate_VersionMustBe1) { ReplSetConfig config; OID newReplSetId = OID::gen(); - ASSERT_OK( - config.initializeForInitiate(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1"))), - newReplSetId)); + config = ReplSetConfig::parseForInitiate(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 + << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1"))), + newReplSetId); ASSERT_EQUALS(ErrorCodes::NewReplicaSetConfigurationIncompatible, validateConfigForInitiate(&rses, config, getGlobalServiceContext()).getStatus()); } @@ -70,16 +70,15 @@ TEST_F(ServiceContextTest, ValidateConfigForInitiate_TermIsAlwaysInitialTerm) { ReplicationCoordinatorExternalStateMock rses; rses.addSelf(HostAndPort("h1")); - ReplSetConfig config; OID newReplSetId = OID::gen(); - ASSERT_OK( - config.initializeForInitiate(BSON("_id" - << "rs0" - << "version" << 1 << "term" << (OpTime::kInitialTerm + 1) - << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1"))), - newReplSetId)); + auto config = ReplSetConfig::parseForInitiate(BSON("_id" + << "rs0" + << "version" << 1 << "term" + << (OpTime::kInitialTerm + 1) + << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1"))), + newReplSetId); ASSERT_OK(validateConfigForInitiate(&rses, config, getGlobalServiceContext()).getStatus()); ASSERT_EQUALS(config.getConfigTerm(), OpTime::kInitialTerm); } @@ -87,17 +86,17 @@ TEST_F(ServiceContextTest, ValidateConfigForInitiate_TermIsAlwaysInitialTerm) { TEST_F(ServiceContextTest, ValidateConfigForInitiate_MustFindSelf) { ReplSetConfig config; OID newReplSetId = OID::gen(); - ASSERT_OK( - config.initializeForInitiate(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2") - << BSON("_id" << 3 << "host" - << "h3"))), - newReplSetId)); + config = ReplSetConfig::parseForInitiate(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 + << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2") + << BSON("_id" << 3 << "host" + << "h3"))), + newReplSetId); ReplicationCoordinatorExternalStateMock notPresentExternalState; ReplicationCoordinatorExternalStateMock presentOnceExternalState; presentOnceExternalState.addSelf(HostAndPort("h2")); @@ -121,18 +120,18 @@ TEST_F(ServiceContextTest, ValidateConfigForInitiate_MustFindSelf) { TEST_F(ServiceContextTest, ValidateConfigForInitiate_SelfMustBeElectable) { ReplSetConfig config; OID newReplSetId = OID::gen(); - ASSERT_OK( - config.initializeForInitiate(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2" - << "priority" << 0) - << BSON("_id" << 3 << "host" - << "h3"))), - newReplSetId)); + config = ReplSetConfig::parseForInitiate(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 + << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2" + << "priority" << 0) + << BSON("_id" << 3 << "host" + << "h3"))), + newReplSetId); ReplicationCoordinatorExternalStateMock presentOnceExternalState; presentOnceExternalState.addSelf(HostAndPort("h2")); @@ -145,15 +144,16 @@ TEST_F(ServiceContextTest, ValidateConfigForInitiate_SelfMustBeElectable) { TEST_F(ServiceContextTest, ValidateConfigForInitiate_WriteConcernMustBeSatisfiable) { ReplSetConfig config; OID newReplSetId = OID::gen(); - ASSERT_OK( - config.initializeForInitiate(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1")) - << "settings" - << BSON("getLastErrorDefaults" << BSON("w" << 2))), - newReplSetId)); + config = + ReplSetConfig::parseForInitiate(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 + << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1")) + << "settings" + << BSON("getLastErrorDefaults" << BSON("w" << 2))), + newReplSetId); ReplicationCoordinatorExternalStateMock presentOnceExternalState; presentOnceExternalState.addSelf(HostAndPort("h2")); @@ -168,7 +168,7 @@ TEST_F(ServiceContextTest, ValidateConfigForInitiate_ArbiterPriorityMustBeZeroOr ReplSetConfig oneConfig; ReplSetConfig twoConfig; OID newReplSetId = OID::gen(); - ASSERT_OK(zeroConfig.initializeForInitiate( + zeroConfig = ReplSetConfig::parseForInitiate( BSON("_id" << "rs0" << "version" << 1 << "protocolVersion" << 1 << "members" @@ -179,9 +179,9 @@ TEST_F(ServiceContextTest, ValidateConfigForInitiate_ArbiterPriorityMustBeZeroOr << "priority" << 0 << "arbiterOnly" << true) << BSON("_id" << 3 << "host" << "h3"))), - newReplSetId)); + newReplSetId); - ASSERT_OK(oneConfig.initializeForInitiate( + oneConfig = ReplSetConfig::parseForInitiate( BSON("_id" << "rs0" << "version" << 1 << "protocolVersion" << 1 << "members" @@ -192,9 +192,9 @@ TEST_F(ServiceContextTest, ValidateConfigForInitiate_ArbiterPriorityMustBeZeroOr << "priority" << 1 << "arbiterOnly" << true) << BSON("_id" << 3 << "host" << "h3"))), - newReplSetId)); + newReplSetId); - ASSERT_OK(twoConfig.initializeForInitiate( + twoConfig = ReplSetConfig::parseForInitiate( BSON("_id" << "rs0" << "version" << 1 << "protocolVersion" << 1 << "members" @@ -205,7 +205,7 @@ TEST_F(ServiceContextTest, ValidateConfigForInitiate_ArbiterPriorityMustBeZeroOr << "priority" << 2 << "arbiterOnly" << true) << BSON("_id" << 3 << "host" << "h3"))), - newReplSetId)); + newReplSetId); ReplicationCoordinatorExternalStateMock presentOnceExternalState; presentOnceExternalState.addSelf(HostAndPort("h1")); @@ -229,32 +229,33 @@ TEST_F(ServiceContextTest, ValidateConfigForInitiate_NewlyAddedFieldNotAllowed) ReplSetConfig firstNewlyAdded; ReplSetConfig lastNewlyAdded; OID newReplSetId = OID::gen(); - ASSERT_OK( - firstNewlyAdded.initializeForInitiate(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "newly_added_h1" - << "newlyAdded" << true) - << BSON("_id" << 2 << "host" - << "h2") - << BSON("_id" << 3 << "host" - << "h3"))), - newReplSetId)); - - ASSERT_OK(lastNewlyAdded.initializeForInitiate( - BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2") - << BSON("_id" << 3 << "host" - << "newly_added_h3" - << "newlyAdded" << true))), - newReplSetId)); + firstNewlyAdded = + ReplSetConfig::parseForInitiate(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 + << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "newly_added_h1" + << "newlyAdded" << true) + << BSON("_id" << 2 << "host" + << "h2") + << BSON("_id" << 3 << "host" + << "h3"))), + newReplSetId); + + lastNewlyAdded = + ReplSetConfig::parseForInitiate(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 + << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2") + << BSON("_id" << 3 << "host" + << "newly_added_h3" + << "newlyAdded" << true))), + newReplSetId); ReplicationCoordinatorExternalStateMock presentOnceExternalState; presentOnceExternalState.addSelf(HostAndPort("h1")); @@ -279,25 +280,25 @@ TEST_F(ServiceContextTest, ValidateConfigForReconfig_NewConfigVersionNumberMustB ReplSetConfig newConfig; // Two configurations, identical except for version. - ASSERT_OK(oldConfig.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2") - << BSON("_id" << 3 << "host" - << "h3"))))); - - ASSERT_OK(newConfig.initialize(BSON("_id" - << "rs0" - << "version" << 3 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2") - << BSON("_id" << 3 << "host" - << "h3"))))); + oldConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2") + << BSON("_id" << 3 << "host" + << "h3")))); + + newConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 3 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2") + << BSON("_id" << 3 << "host" + << "h3")))); ASSERT_OK(oldConfig.validate()); ASSERT_OK(newConfig.validate()); @@ -323,25 +324,25 @@ TEST_F(ServiceContextTest, ValidateConfigForReconfig_NewConfigMustNotChangeSetNa ReplSetConfig newConfig; // Two configurations, compatible except for set name. - ASSERT_OK(oldConfig.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2") - << BSON("_id" << 3 << "host" - << "h3"))))); - - ASSERT_OK(newConfig.initialize(BSON("_id" - << "rs1" - << "version" << 3 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2") - << BSON("_id" << 3 << "host" - << "h3"))))); + oldConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2") + << BSON("_id" << 3 << "host" + << "h3")))); + + newConfig = ReplSetConfig::parse(BSON("_id" + << "rs1" + << "version" << 3 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2") + << BSON("_id" << 3 << "host" + << "h3")))); ASSERT_OK(oldConfig.validate()); ASSERT_OK(newConfig.validate()); @@ -360,27 +361,27 @@ TEST_F(ServiceContextTest, ValidateConfigForReconfig_NewConfigMustNotChangeSetId ReplSetConfig newConfig; // Two configurations, compatible except for set ID. - ASSERT_OK(oldConfig.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2") - << BSON("_id" << 3 << "host" - << "h3")) - << "settings" << BSON("replicaSetId" << OID::gen())))); - - ASSERT_OK(newConfig.initialize(BSON("_id" - << "rs0" - << "version" << 3 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2") - << BSON("_id" << 3 << "host" - << "h3")) - << "settings" << BSON("replicaSetId" << OID::gen())))); + oldConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2") + << BSON("_id" << 3 << "host" + << "h3")) + << "settings" << BSON("replicaSetId" << OID::gen()))); + + newConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 3 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2") + << BSON("_id" << 3 << "host" + << "h3")) + << "settings" << BSON("replicaSetId" << OID::gen()))); ASSERT_OK(oldConfig.validate()); ASSERT_OK(newConfig.validate()); @@ -403,42 +404,43 @@ TEST_F(ServiceContextTest, ValidateConfigForReconfig_NewConfigMustNotFlipBuildIn // Three configurations, two compatible except that h2 flips the buildIndex flag. // The third, compatible with the first. - ASSERT_OK(oldConfig.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2" - << "buildIndexes" << false - << "priority" << 0) - << BSON("_id" << 3 << "host" - << "h3"))))); - - ASSERT_OK(newConfig.initialize(BSON("_id" - << "rs0" - << "version" << 3 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2" - << "buildIndexes" << true - << "priority" << 0) - << BSON("_id" << 3 << "host" - << "h3"))))); + oldConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2" + << "buildIndexes" << false + << "priority" << 0) + << BSON("_id" << 3 << "host" + << "h3")))); - ASSERT_OK( - oldConfigRefresh.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2" - << "buildIndexes" << false - << "priority" << 0) - << BSON("_id" << 3 << "host" - << "h3"))))); + newConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 3 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2" + << "buildIndexes" << true + << "priority" << 0) + << BSON("_id" << 3 << "host" + << "h3")))); + + + oldConfigRefresh = + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2" + << "buildIndexes" << false + << "priority" << 0) + << BSON("_id" << 3 << "host" + << "h3")))); ASSERT_OK(oldConfig.validate()); ASSERT_OK(newConfig.validate()); @@ -462,39 +464,40 @@ TEST_F(ServiceContextTest, ValidateConfigForReconfig_NewConfigMustNotFlipArbiter // Three configurations, two compatible except that h2 flips the arbiterOnly flag. // The third, compatible with the first. - ASSERT_OK(oldConfig.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2" - << "arbiterOnly" << false) - << BSON("_id" << 3 << "host" - << "h3"))))); - - ASSERT_OK(newConfig.initialize(BSON("_id" - << "rs0" - << "version" << 3 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2" - << "arbiterOnly" << true) - << BSON("_id" << 3 << "host" - << "h3"))))); + oldConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2" + << "arbiterOnly" << false) + << BSON("_id" << 3 << "host" + << "h3")))); - ASSERT_OK( - oldConfigRefresh.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2" - << "arbiterOnly" << false) - << BSON("_id" << 3 << "host" - << "h3"))))); + newConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 3 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2" + << "arbiterOnly" << true) + << BSON("_id" << 3 << "host" + << "h3")))); + + + oldConfigRefresh = + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2" + << "arbiterOnly" << false) + << BSON("_id" << 3 << "host" + << "h3")))); ASSERT_OK(oldConfig.validate()); ASSERT_OK(newConfig.validate()); @@ -520,32 +523,32 @@ TEST_F(ServiceContextTest, ValidateConfigForReconfig_HostAndIdRemappingRestricte ReplSetConfig illegalNewConfigReusingHost; ReplSetConfig illegalNewConfigReusingId; - ASSERT_OK(oldConfig.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2") - << BSON("_id" << 3 << "host" - << "h3"))))); + oldConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2") + << BSON("_id" << 3 << "host" + << "h3")))); ASSERT_OK(oldConfig.validate()); // // Here, the new config is valid because we've replaced (2, "h2") with // (4, "h4"), so neither the member _id or host name were reused. // - ASSERT_OK( - legalNewConfigWithNewHostAndId.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 4 << "host" - << "h4") - << BSON("_id" << 3 << "host" - << "h3"))))); + + legalNewConfigWithNewHostAndId = + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 4 << "host" + << "h4") + << BSON("_id" << 3 << "host" + << "h3")))); ASSERT_OK(legalNewConfigWithNewHostAndId.validate()); ASSERT_OK( validateConfigForReconfig(oldConfig, @@ -557,16 +560,16 @@ TEST_F(ServiceContextTest, ValidateConfigForReconfig_HostAndIdRemappingRestricte // Here, the new config is invalid because we've reused host name "h2" with // new _id 4. // - ASSERT_OK(illegalNewConfigReusingHost.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" - << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 4 << "host" - << "h2") - << BSON("_id" << 3 << "host" - << "h3"))))); + illegalNewConfigReusingHost = + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 4 << "host" + << "h2") + << BSON("_id" << 3 << "host" + << "h3")))); ASSERT_OK(illegalNewConfigReusingHost.validate()); ASSERT_EQUALS(ErrorCodes::NewReplicaSetConfigurationIncompatible, validateConfigForReconfig(oldConfig, illegalNewConfigReusingHost, false)); @@ -577,16 +580,16 @@ TEST_F(ServiceContextTest, ValidateConfigForReconfig_HostAndIdRemappingRestricte // Here, the new config is valid, because all we've changed is the name of // the host representing _id 2. // - ASSERT_OK(illegalNewConfigReusingId.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h4") - << BSON("_id" << 3 << "host" - << "h3"))))); + illegalNewConfigReusingId = + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h4") + << BSON("_id" << 3 << "host" + << "h3")))); ASSERT_OK(illegalNewConfigReusingId.validate()); ASSERT_OK(validateConfigForReconfig(oldConfig, illegalNewConfigReusingId, false)); } @@ -600,50 +603,50 @@ TEST_F(ServiceContextTest, ValidateConfigForReconfig_ArbiterPriorityValueMustBeZ ReplSetConfig oneConfig; ReplSetConfig twoConfig; - ASSERT_OK(oldConfig.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2" - << "arbiterOnly" << true) - << BSON("_id" << 3 << "host" - << "h3"))))); - - ASSERT_OK(zeroConfig.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2" - << "priority" << 0 - << "arbiterOnly" << true) - << BSON("_id" << 3 << "host" - << "h3"))))); - ASSERT_OK(oneConfig.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2" - << "priority" << 1 - << "arbiterOnly" << true) - << BSON("_id" << 3 << "host" - << "h3"))))); - ASSERT_OK(twoConfig.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2" - << "priority" << 2 - << "arbiterOnly" << true) - << BSON("_id" << 3 << "host" - << "h3"))))); + oldConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2" + << "arbiterOnly" << true) + << BSON("_id" << 3 << "host" + << "h3")))); + + zeroConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2" + << "priority" << 0 + << "arbiterOnly" << true) + << BSON("_id" << 3 << "host" + << "h3")))); + oneConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2" + << "priority" << 1 + << "arbiterOnly" << true) + << BSON("_id" << 3 << "host" + << "h3")))); + twoConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2" + << "priority" << 2 + << "arbiterOnly" << true) + << BSON("_id" << 3 << "host" + << "h3")))); ASSERT_OK(oldConfig.validate()); ASSERT_OK(zeroConfig.validate()); @@ -664,15 +667,15 @@ TEST_F(ServiceContextTest, ValidateConfigForInitiate_NewConfigInvalid) { // wrong with the new config. ReplSetConfig newConfig; OID newReplSetId = OID::gen(); - ASSERT_OK(newConfig.initializeForInitiate(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "h2") - << BSON("_id" << 0 << "host" - << "h3"))), - newReplSetId)); + newConfig = ReplSetConfig::parseForInitiate(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 + << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "h2") + << BSON("_id" << 0 << "host" + << "h3"))), + newReplSetId); ReplicationCoordinatorExternalStateMock presentOnceExternalState; presentOnceExternalState.addSelf(HostAndPort("h2")); @@ -687,20 +690,20 @@ TEST_F(ServiceContextTest, ValidateConfigForReconfig_NewConfigInvalid) { // config is invalid, validateConfigForReconfig will return a status indicating what is // wrong with the new config. ReplSetConfig oldConfig; - ASSERT_OK(oldConfig.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "h2"))))); + oldConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "h2")))); ReplSetConfig newConfig; - ASSERT_OK(newConfig.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "h2") - << BSON("_id" << 0 << "host" - << "h3"))))); + newConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "h2") + << BSON("_id" << 0 << "host" + << "h3")))); ReplicationCoordinatorExternalStateMock presentOnceExternalState; presentOnceExternalState.addSelf(HostAndPort("h2")); @@ -714,20 +717,20 @@ TEST_F(ServiceContextTest, ValidateConfigForReconfig_NewConfigWriteConcernNotSat // new config is invalid, validateConfigForReconfig will return a status indicating what is // wrong with the new config. ReplSetConfig oldConfig; - ASSERT_OK(oldConfig.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "h2"))))); + oldConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "h2")))); ReplSetConfig newConfig; - ASSERT_OK(newConfig.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "h2")) - << "settings" - << BSON("getLastErrorDefaults" << BSON("w" << 2))))); + newConfig = + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "h2")) + << "settings" << BSON("getLastErrorDefaults" << BSON("w" << 2)))); ReplicationCoordinatorExternalStateMock presentOnceExternalState; presentOnceExternalState.addSelf(HostAndPort("h2")); @@ -743,13 +746,13 @@ TEST_F(ServiceContextTest, ValidateConfigForStartUp_NewConfigInvalid) { // config is invalid, validateConfigForStartUp will return a status indicating what is wrong // with the new config. ReplSetConfig newConfig; - ASSERT_OK(newConfig.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "h2") - << BSON("_id" << 0 << "host" - << "h3"))))); + newConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "h2") + << BSON("_id" << 0 << "host" + << "h3")))); ReplicationCoordinatorExternalStateMock presentOnceExternalState; presentOnceExternalState.addSelf(HostAndPort("h2")); @@ -763,14 +766,14 @@ TEST_F(ServiceContextTest, ValidateConfigForStartUp_NewConfigValid) { // The new config is valid. This tests that validateConfigForStartUp will return a // Status::OK() indicating the validity of this configuration. ReplSetConfig newConfig; - ASSERT_OK(newConfig.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "h2" - << "priority" << 3) - << BSON("_id" << 1 << "host" - << "h3"))))); + newConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "h2" + << "priority" << 3) + << BSON("_id" << 1 << "host" + << "h3")))); ReplicationCoordinatorExternalStateMock presentOnceExternalState; presentOnceExternalState.addSelf(HostAndPort("h2")); @@ -784,13 +787,13 @@ TEST_F(ServiceContextTest, ValidateConfigForStartUp_NewConfigWriteConcernNotSati // created anymore, but we allow any which exist to pass and the database to start up to // maintain backwards compatibility. ReplSetConfig newConfig; - ASSERT_OK(newConfig.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "h2")) - << "settings" - << BSON("getLastErrorDefaults" << BSON("w" << 2))))); + newConfig = + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "h2")) + << "settings" << BSON("getLastErrorDefaults" << BSON("w" << 2)))); ReplicationCoordinatorExternalStateMock presentOnceExternalState; presentOnceExternalState.addSelf(HostAndPort("h2")); @@ -804,13 +807,13 @@ TEST_F(ServiceContextTest, ValidateConfigForHeartbeatReconfig_NewConfigInvalid) // config is invalid, validateConfigForHeartbeatReconfig will return a status indicating // what is wrong with the new config. ReplSetConfig newConfig; - ASSERT_OK(newConfig.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "h2") - << BSON("_id" << 0 << "host" - << "h3"))))); + newConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "h2") + << BSON("_id" << 0 << "host" + << "h3")))); ReplicationCoordinatorExternalStateMock presentOnceExternalState; presentOnceExternalState.addSelf(HostAndPort("h2")); @@ -824,13 +827,13 @@ TEST_F(ServiceContextTest, ValidateConfigForHeartbeatReconfig_NewConfigValid) { // The new config is valid. This tests that validateConfigForHeartbeatReconfig will return // a Status::OK() indicating the validity of this config change. ReplSetConfig newConfig; - ASSERT_OK(newConfig.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "h2") - << BSON("_id" << 1 << "host" - << "h3"))))); + newConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "h2") + << BSON("_id" << 1 << "host" + << "h3")))); ReplicationCoordinatorExternalStateMock presentOnceExternalState; presentOnceExternalState.addSelf(HostAndPort("h2")); @@ -843,15 +846,15 @@ TEST_F(ServiceContextTest, ValidateConfigForHeartbeatReconfig_NewConfigWriteConc // The new config contains an unsatisfiable write concern. We don't allow these configs to be // created anymore, but we allow any which exist to be received in a heartbeat. ReplSetConfig newConfig; - ASSERT_OK(newConfig.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "h2") - << BSON("_id" << 1 << "host" - << "h3")) - << "settings" - << BSON("getLastErrorDefaults" << BSON("w" << 2))))); + newConfig = + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "h2") + << BSON("_id" << 1 << "host" + << "h3")) + << "settings" << BSON("getLastErrorDefaults" << BSON("w" << 2)))); ReplicationCoordinatorExternalStateMock presentOnceExternalState; presentOnceExternalState.addSelf(HostAndPort("h2")); @@ -864,23 +867,23 @@ TEST_F(ServiceContextTest, ValidateForReconfig_ForceStillNeedsValidConfig) { // The new config is invalid due to two nodes with the same _id value. This tests that // ValidateForReconfig fails with an invalid config, even if force is true. ReplSetConfig oldConfig; - ASSERT_OK(oldConfig.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "h2") - << BSON("_id" << 1 << "host" - << "h3"))))); + oldConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "h2") + << BSON("_id" << 1 << "host" + << "h3")))); ReplSetConfig newConfig; - ASSERT_OK(newConfig.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "h2") - << BSON("_id" << 0 << "host" - << "h3"))))); + newConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "h2") + << BSON("_id" << 0 << "host" + << "h3")))); ReplicationCoordinatorExternalStateMock presentOnceExternalState; presentOnceExternalState.addSelf(HostAndPort("h2")); @@ -918,17 +921,16 @@ BSONObj m4_NonVoting = BSON("_id" << 4 << "host" << "votes" << 0 << "priority" << 0); // Test helper to initialize config more concisely. -Status initializeConfig(ReplSetConfig& cfg, std::string id, int version, BSONArray members) { - return cfg.initialize(BSON("_id" << id << "version" << version << "protocolVersion" << 1 - << "members" << members)); +ReplSetConfig initializeConfig(std::string id, int version, BSONArray members) { + return ReplSetConfig::parse(BSON("_id" << id << "version" << version << "protocolVersion" << 1 + << "members" << members)); } // Validate reconfig between the two given member arrays and return the Status. Status validateMemberReconfig(BSONArray oldMembers, BSONArray newMembers, BSONObj selfMember) { // Initialize configs. - ReplSetConfig oldConfig, newConfig; - ASSERT_OK(initializeConfig(oldConfig, "rs0", 1, oldMembers)); - ASSERT_OK(initializeConfig(newConfig, "rs0", 2, newMembers)); + auto oldConfig = initializeConfig("rs0", 1, oldMembers); + auto newConfig = initializeConfig("rs0", 2, newMembers); ReplicationCoordinatorExternalStateMock presentOnceExternalState; presentOnceExternalState.addSelf(HostAndPort(selfMember.getStringField("host"))); @@ -1020,77 +1022,77 @@ TEST_F(ServiceContextTest, SameConfigContents) { << "2")); // Same contents with different version. - ASSERT_OK(configA.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "term" << 1 << "protocolVersion" << 1 - << "members" << members1))); - ASSERT_OK(configB.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "term" << 1 << "protocolVersion" << 1 - << "members" << members1))); + configA = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "term" << 1 << "protocolVersion" << 1 + << "members" << members1)); + configB = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "term" << 1 << "protocolVersion" << 1 + << "members" << members1)); ASSERT(sameConfigContents(configA, configB)); // Same contents with different term. - ASSERT_OK(configA.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "term" << 1 << "protocolVersion" << 1 - << "members" << members1))); - ASSERT_OK(configB.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "term" << 2 << "protocolVersion" << 1 - << "members" << members1))); + configA = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "term" << 1 << "protocolVersion" << 1 + << "members" << members1)); + configB = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "term" << 2 << "protocolVersion" << 1 + << "members" << members1)); ASSERT(sameConfigContents(configA, configB)); // Same contents with different term and version. - ASSERT_OK(configA.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "term" << 1 << "protocolVersion" << 1 - << "members" << members1))); - ASSERT_OK(configB.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "term" << 2 << "protocolVersion" << 1 - << "members" << members1))); + configA = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "term" << 1 << "protocolVersion" << 1 + << "members" << members1)); + configB = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "term" << 2 << "protocolVersion" << 1 + << "members" << members1)); ASSERT(sameConfigContents(configA, configB)); // Different config settings. - ASSERT_OK(configA.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "term" << 1 << "protocolVersion" << 1 - << "members" << members1 << "settings" - << BSON("electionTimeoutMillis" << 1000)))); - ASSERT_OK(configB.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "term" << 1 << "protocolVersion" << 1 - << "members" << members1 << "settings" - << BSON("electionTimeoutMillis" << 2000)))); + configA = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "term" << 1 << "protocolVersion" << 1 + << "members" << members1 << "settings" + << BSON("electionTimeoutMillis" << 1000))); + configB = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "term" << 1 << "protocolVersion" << 1 + << "members" << members1 << "settings" + << BSON("electionTimeoutMillis" << 2000))); ASSERT_FALSE(sameConfigContents(configA, configB)); // Different members. - ASSERT_OK(configA.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "term" << 1 << "protocolVersion" << 1 - << "members" << members1 << "settings" - << BSON("electionTimeoutMillis" << 1000)))); - ASSERT_OK(configB.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "term" << 1 << "protocolVersion" << 1 - << "members" << members2 << "settings" - << BSON("electionTimeoutMillis" << 2000)))); + configA = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "term" << 1 << "protocolVersion" << 1 + << "members" << members1 << "settings" + << BSON("electionTimeoutMillis" << 1000))); + configB = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "term" << 1 << "protocolVersion" << 1 + << "members" << members2 << "settings" + << BSON("electionTimeoutMillis" << 2000))); ASSERT_FALSE(sameConfigContents(configA, configB)); } TEST_F(ServiceContextTest, FindSelfInConfig) { // We must be able to find ourself in the new config. ReplSetConfig newConfig; - ASSERT_OK(newConfig.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2") - << BSON("_id" << 3 << "host" - << "h3"))))); + newConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2") + << BSON("_id" << 3 << "host" + << "h3")))); ReplicationCoordinatorExternalStateMock notPresentExternalState; ReplicationCoordinatorExternalStateMock presentOnceExternalState; presentOnceExternalState.addSelf(HostAndPort("h2")); @@ -1125,16 +1127,16 @@ TEST_F(ServiceContextTest, FindSelfInConfig) { &presentOnceExternalState, newConfig, getGlobalServiceContext()))); // We must be electable in the new config. - ASSERT_OK(newConfig.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1") - << BSON("_id" << 2 << "host" - << "h2" - << "priority" << 0) - << BSON("_id" << 3 << "host" - << "h3"))))); + newConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1") + << BSON("_id" << 2 << "host" + << "h2" + << "priority" << 0) + << BSON("_id" << 3 << "host" + << "h3")))); ASSERT_EQUALS( ErrorCodes::NodeNotElectable, diff --git a/src/mongo/db/repl/repl_set_config_test.cpp b/src/mongo/db/repl/repl_set_config_test.cpp index f7a68acd0bc..20d7bb4270d 100644 --- a/src/mongo/db/repl/repl_set_config_test.cpp +++ b/src/mongo/db/repl/repl_set_config_test.cpp @@ -61,13 +61,13 @@ BSONObj createConfigDoc(int members, int voters = ReplSetConfig::kMaxVotingMembe } TEST(ReplSetConfig, ParseMinimalConfigAndCheckDefaults) { - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "term" << 1 << "protocolVersion" << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "term" << 1 << "protocolVersion" << 1 + << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345"))))); ASSERT_OK(config.validate()); ASSERT_EQUALS("rs0", config.getReplSetName()); ASSERT_EQUALS(1, config.getConfigVersion()); @@ -90,25 +90,24 @@ TEST(ReplSetConfig, ParseMinimalConfigAndCheckDefaults) { } TEST(ReplSetConfig, ParseLargeConfigAndCheckAccessors) { - ReplSetConfig config; - ASSERT_OK( - config.initialize(BSON("_id" - << "rs0" - << "version" << 1234 << "term" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 234 << "host" - << "localhost:12345" - << "tags" - << BSON("NYC" - << "NY"))) - << "protocolVersion" << 1 << "settings" - << BSON("getLastErrorDefaults" - << BSON("w" - << "majority") - << "getLastErrorModes" - << BSON("eastCoast" << BSON("NYC" << 1)) << "chainingAllowed" - << false << "heartbeatIntervalMillis" << 5000 - << "heartbeatTimeoutSecs" << 120 << "electionTimeoutMillis" - << 10)))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1234 << "term" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 234 << "host" + << "localhost:12345" + << "tags" + << BSON("NYC" + << "NY"))) + << "protocolVersion" << 1 << "settings" + << BSON("getLastErrorDefaults" + << BSON("w" + << "majority") + << "getLastErrorModes" + << BSON("eastCoast" << BSON("NYC" << 1)) + << "chainingAllowed" << false << "heartbeatIntervalMillis" + << 5000 << "heartbeatTimeoutSecs" << 120 + << "electionTimeoutMillis" << 10)))); ASSERT_OK(config.validate()); ASSERT_EQUALS("rs0", config.getReplSetName()); ASSERT_EQUALS(1234, config.getConfigVersion()); @@ -130,21 +129,21 @@ TEST(ReplSetConfig, ParseLargeConfigAndCheckAccessors) { } TEST(ReplSetConfig, GetConnectionStringFiltersHiddenNodes) { - ReplSetConfig config; - ASSERT_OK( - config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:11111") - << BSON("_id" << 1 << "host" - << "localhost:22222" - << "arbiterOnly" << true) - << BSON("_id" << 2 << "host" - << "localhost:33333" - << "hidden" << true << "priority" << 0) - << BSON("_id" << 3 << "host" - << "localhost:44444"))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:11111") + << BSON("_id" << 1 << "host" + << "localhost:22222" + << "arbiterOnly" << true) + << BSON("_id" << 2 << "host" + << "localhost:33333" + << "hidden" << true << "priority" + << 0) + << BSON("_id" << 3 << "host" + << "localhost:44444"))))); ASSERT_OK(config.validate()); ASSERT_EQUALS(ConnectionString::forReplicaSet( "rs0", {HostAndPort{"localhost:11111"}, HostAndPort{"localhost:44444"}}) @@ -153,249 +152,253 @@ TEST(ReplSetConfig, GetConnectionStringFiltersHiddenNodes) { } TEST(ReplSetConfig, MajorityCalculationThreeVotersNoArbiters) { - ReplSetConfig config; - ASSERT_OK( - config.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "h1:1") - << BSON("_id" << 2 << "host" - << "h2:1") - << BSON("_id" << 3 << "host" - << "h3:1") - << BSON("_id" << 4 << "host" - << "h4:1" - << "votes" << 0 << "priority" << 0) - << BSON("_id" << 5 << "host" - << "h5:1" - << "votes" << 0 << "priority" << 0))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1:1") + << BSON("_id" << 2 << "host" + << "h2:1") + << BSON("_id" << 3 << "host" + << "h3:1") + << BSON("_id" << 4 << "host" + << "h4:1" + << "votes" << 0 << "priority" << 0) + << BSON("_id" << 5 << "host" + << "h5:1" + << "votes" << 0 << "priority" + << 0))))); ASSERT_OK(config.validate()); ASSERT_EQUALS(2, config.getWriteMajority()); } TEST(ReplSetConfig, MajorityCalculationNearlyHalfArbiters) { - ReplSetConfig config; - ASSERT_OK( - config.initialize(BSON("_id" - << "mySet" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("host" - << "node1:12345" - << "_id" << 0) - << BSON("host" - << "node2:12345" - << "_id" << 1) - << BSON("host" - << "node3:12345" - << "_id" << 2) - << BSON("host" - << "node4:12345" - << "_id" << 3 << "arbiterOnly" << true) - << BSON("host" - << "node5:12345" - << "_id" << 4 << "arbiterOnly" << true))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "mySet" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("host" + << "node1:12345" + << "_id" << 0) + << BSON("host" + << "node2:12345" + << "_id" << 1) + << BSON("host" + << "node3:12345" + << "_id" << 2) + << BSON("host" + << "node4:12345" + << "_id" << 3 << "arbiterOnly" << true) + << BSON("host" + << "node5:12345" + << "_id" << 4 << "arbiterOnly" << true))))); ASSERT_OK(config.validate()); ASSERT_EQUALS(3, config.getWriteMajority()); } TEST(ReplSetConfig, MajorityCalculationEvenNumberOfMembers) { - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "mySet" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("host" - << "node1:12345" - << "_id" << 0) - << BSON("host" - << "node2:12345" - << "_id" << 1) - << BSON("host" - << "node3:12345" - << "_id" << 2) - << BSON("host" - << "node4:12345" - << "_id" << 3))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "mySet" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("host" + << "node1:12345" + << "_id" << 0) + << BSON("host" + << "node2:12345" + << "_id" << 1) + << BSON("host" + << "node3:12345" + << "_id" << 2) + << BSON("host" + << "node4:12345" + << "_id" << 3))))); ASSERT_OK(config.validate()); ASSERT_EQUALS(3, config.getWriteMajority()); } TEST(ReplSetConfig, MajorityCalculationNearlyHalfSecondariesNoVotes) { - ReplSetConfig config; - ASSERT_OK( - config.initialize(BSON("_id" - << "mySet" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY( - BSON("host" - << "node1:12345" - << "_id" << 0) - << BSON("host" - << "node2:12345" - << "_id" << 1 << "votes" << 0 << "priority" << 0) - << BSON("host" - << "node3:12345" - << "_id" << 2 << "votes" << 0 << "priority" << 0) - << BSON("host" - << "node4:12345" - << "_id" << 3) - << BSON("host" - << "node5:12345" - << "_id" << 4))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "mySet" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY( + BSON("host" + << "node1:12345" + << "_id" << 0) + << BSON("host" + << "node2:12345" + << "_id" << 1 << "votes" << 0 << "priority" << 0) + << BSON("host" + << "node3:12345" + << "_id" << 2 << "votes" << 0 << "priority" << 0) + << BSON("host" + << "node4:12345" + << "_id" << 3) + << BSON("host" + << "node5:12345" + << "_id" << 4))))); ASSERT_OK(config.validate()); ASSERT_EQUALS(2, config.getWriteMajority()); } TEST(ReplSetConfig, ParseFailsWithBadOrMissingIdField) { - ReplSetConfig config; // Replica set name must be a string. - ASSERT_EQUALS(ErrorCodes::TypeMismatch, - config.initialize(BSON("_id" << 1 << "version" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" << 1 << "version" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")))), + ExceptionFor<ErrorCodes::TypeMismatch>); // Replica set name must be present. - ASSERT_NOT_OK( - config.initialize(BSON("version" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); + ASSERT_THROWS( + ReplSetConfig::parse(BSON("version" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")))), + DBException); // Replica set name must be non-empty. - ASSERT_NOT_OK(config.initialize(BSON("_id" - << "" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")))), + DBException); } TEST(ReplSetConfig, ParseFailsWithBadOrMissingVersionField) { - ReplSetConfig config; // Config version field must be present. - ASSERT_NOT_OK(config.initialize(BSON("_id" - << "rs0" - << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); - ASSERT_EQUALS(ErrorCodes::TypeMismatch, - config.initialize(BSON("_id" - << "rs0" - << "version" - << "1" - << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); - - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1.0 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")))), + DBException); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" + << "1" + << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")))), + ExceptionFor<ErrorCodes::TypeMismatch>); + + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1.0 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345"))))); ASSERT_OK(config.validate()); - ASSERT_NOT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 0.0 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); - ASSERT_NOT_OK( - config.initialize(BSON("_id" - << "rs0" - << "version" - << static_cast<long long>(std::numeric_limits<int>::max()) + 1 - << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); + ASSERT_THROWS( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 0.0 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")))), + DBException); + ASSERT_THROWS( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" + << static_cast<long long>(std::numeric_limits<int>::max()) + 1 + << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")))), + DBException); } TEST(ReplSetConfig, ParseFailsWithBadOrMissingTermField) { - ReplSetConfig config; // Absent term field should set a default. - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345"))))); ASSERT_EQUALS(config.getConfigTerm(), -1); // Serializing the config to BSON should omit a term field with value -1. ASSERT_FALSE(config.toBSON().hasField(ReplSetConfig::kConfigTermFieldName)); - ASSERT_EQUALS(ErrorCodes::TypeMismatch, - config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "term" - << "1" - << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); - - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "term" << 1.0 << "protocolVersion" << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "term" + << "1" + << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")))), + ExceptionFor<ErrorCodes::TypeMismatch>); + + config = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "term" << 1.0 << "protocolVersion" << 1 + << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")))); ASSERT_OK(config.validate()); - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "term" << 0.0 << "protocolVersion" << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); + config = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "term" << 0.0 << "protocolVersion" << 1 + << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")))); ASSERT_OK(config.validate()); // Config term can be -1. - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "term" << -1.0 << "protocolVersion" << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); + config = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "term" << -1.0 << "protocolVersion" << 1 + << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")))); ASSERT_OK(config.validate()); ASSERT_FALSE(config.toBSON().hasField(ReplSetConfig::kConfigTermFieldName)); - ASSERT_NOT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "term" << -2.0 << "protocolVersion" - << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); - ASSERT_NOT_OK( - config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "term" - << static_cast<long long>(std::numeric_limits<int>::max()) + 1 - << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "term" << -2.0 << "protocolVersion" + << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")))), + DBException); + ASSERT_THROWS( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "term" + << static_cast<long long>(std::numeric_limits<int>::max()) + 1 + << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")))), + DBException); } TEST(ReplSetConfig, ParseFailsWithBadMembers) { - ReplSetConfig config; - ASSERT_EQUALS(ErrorCodes::TypeMismatch, - config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345") - << "localhost:23456")))); - ASSERT_NOT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("host" - << "localhost:12345"))))); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345") + << "localhost:23456"))), + ExceptionFor<ErrorCodes::TypeMismatch>); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("host" + << "localhost:12345")))), + DBException); } TEST(ReplSetConfig, ParseFailsWithLocalNonLocalHostMix) { - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost") - << BSON("_id" << 1 << "host" - << "otherhost"))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost") + << BSON("_id" << 1 << "host" + << "otherhost"))))); ASSERT_EQUALS(ErrorCodes::BadValue, config.validate()); } TEST(ReplSetConfig, ParseFailsWithNoElectableNodes) { - ReplSetConfig config; const BSONObj configBsonNoElectableNodes = BSON("_id" << "rs0" << "version" << 1 << "protocolVersion" << 1 @@ -408,7 +411,7 @@ TEST(ReplSetConfig, ParseFailsWithNoElectableNodes) { << "priority" << 0))); - ASSERT_OK(config.initialize(configBsonNoElectableNodes)); + ReplSetConfig config(ReplSetConfig::parse(configBsonNoElectableNodes)); ASSERT_EQUALS(ErrorCodes::BadValue, config.validate()); const BSONObj configBsonNoElectableNodesOneArbiter = @@ -422,7 +425,7 @@ TEST(ReplSetConfig, ParseFailsWithNoElectableNodes) { << "localhost:2" << "priority" << 0))); - ASSERT_OK(config.initialize(configBsonNoElectableNodesOneArbiter)); + config = ReplSetConfig::parse(configBsonNoElectableNodesOneArbiter); ASSERT_EQUALS(ErrorCodes::BadValue, config.validate()); const BSONObj configBsonNoElectableNodesTwoArbiters = @@ -436,7 +439,7 @@ TEST(ReplSetConfig, ParseFailsWithNoElectableNodes) { << "localhost:2" << "arbiterOnly" << 1))); - ASSERT_OK(config.initialize(configBsonNoElectableNodesOneArbiter)); + config = ReplSetConfig::parse(configBsonNoElectableNodesOneArbiter); ASSERT_EQUALS(ErrorCodes::BadValue, config.validate()); const BSONObj configBsonOneElectableNode = BSON("_id" @@ -450,7 +453,7 @@ TEST(ReplSetConfig, ParseFailsWithNoElectableNodes) { << "localhost:2" << "priority" << 1))); - ASSERT_OK(config.initialize(configBsonOneElectableNode)); + config = ReplSetConfig::parse(configBsonOneElectableNode); ASSERT_OK(config.validate()); } @@ -467,7 +470,7 @@ TEST(ReplSetConfig, ParseFailsWithTooFewVoters) { << "localhost:2" << "votes" << 0 << "priority" << 0))); - ASSERT_OK(config.initialize(configBsonNoVoters)); + config = ReplSetConfig::parse(configBsonNoVoters); ASSERT_EQUALS(ErrorCodes::BadValue, config.validate()); const BSONObj configBsonOneVoter = BSON("_id" @@ -480,15 +483,15 @@ TEST(ReplSetConfig, ParseFailsWithTooFewVoters) { << BSON("_id" << 1 << "host" << "localhost:2" << "votes" << 1))); - ASSERT_OK(config.initialize(configBsonOneVoter)); + config = ReplSetConfig::parse(configBsonOneVoter); ASSERT_OK(config.validate()); } TEST(ReplSetConfig, ParseFailsWithTooManyVoters) { - ReplSetConfig config; - ASSERT_OK(config.initialize(createConfigDoc(8, ReplSetConfig::kMaxVotingMembers))); + ReplSetConfig config( + ReplSetConfig::parse(createConfigDoc(8, ReplSetConfig::kMaxVotingMembers))); ASSERT_OK(config.validate()); - ASSERT_OK(config.initialize(createConfigDoc(8, ReplSetConfig::kMaxVotingMembers + 1))); + config = ReplSetConfig::parse(createConfigDoc(8, ReplSetConfig::kMaxVotingMembers + 1)); ASSERT_NOT_OK(config.validate()); } @@ -501,7 +504,7 @@ TEST(ReplSetConfig, ParseFailsWithDuplicateHost) { << "localhost:1") << BSON("_id" << 1 << "host" << "localhost:1"))); - ASSERT_OK(config.initialize(configBson)); + config = ReplSetConfig::parse(configBson); ASSERT_EQUALS(ErrorCodes::BadValue, config.validate()); } @@ -538,43 +541,45 @@ TEST(ReplSetConfig, ParseFailsWithTooManyNodes) { const BSONObj configBsonTooManyNodes = configDoc.getObject(); - ASSERT_OK(config.initialize(configBsonMaxNodes)); + config = ReplSetConfig::parse(configBsonMaxNodes); ASSERT_OK(config.validate()); - ASSERT_OK(config.initialize(configBsonTooManyNodes)); + config = ReplSetConfig::parse(configBsonTooManyNodes); ASSERT_EQUALS(ErrorCodes::BadValue, config.validate()); } TEST(ReplSetConfig, ParseFailsWithUnexpectedField) { ReplSetConfig config; - ASSERT_NOT_OK( - config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "unexpectedfield" - << "value" - << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); + ASSERT_THROWS( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "unexpectedfield" + << "value" + << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")))), + DBException); } TEST(ReplSetConfig, ParseFailsWithNonArrayMembersField) { ReplSetConfig config; - ASSERT_NOT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << "value"))); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << "value")), + DBException); } TEST(ReplSetConfig, ParseFailsWithNonNumericHeartbeatIntervalMillisField) { ReplSetConfig config; - Status status = config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" - << BSON("heartbeatIntervalMillis" - << "no"))); - ASSERT_EQUALS(ErrorCodes::TypeMismatch, status); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" + << BSON("heartbeatIntervalMillis" + << "no"))), + ExceptionFor<ErrorCodes::TypeMismatch>); ASSERT_FALSE(config.isInitialized()); @@ -584,273 +589,277 @@ TEST(ReplSetConfig, ParseFailsWithNonNumericHeartbeatIntervalMillisField) { TEST(ReplSetConfig, ParseFailsWithNonNumericElectionTimeoutMillisField) { ReplSetConfig config; - Status status = config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" - << BSON("electionTimeoutMillis" - << "no"))); - ASSERT_EQUALS(ErrorCodes::TypeMismatch, status); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" + << BSON("electionTimeoutMillis" + << "no"))), + ExceptionFor<ErrorCodes::TypeMismatch>); } TEST(ReplSetConfig, ParseFailsWithNonNumericHeartbeatTimeoutSecsField) { ReplSetConfig config; - Status status = config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" - << BSON("heartbeatTimeoutSecs" - << "no"))); - ASSERT_EQUALS(ErrorCodes::TypeMismatch, status); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" + << BSON("heartbeatTimeoutSecs" + << "no"))), + ExceptionFor<ErrorCodes::TypeMismatch>); } TEST(ReplSetConfig, ParseFailsWithNonBoolChainingAllowedField) { ReplSetConfig config; - Status status = config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" - << BSON("chainingAllowed" - << "no"))); - ASSERT_EQUALS(ErrorCodes::TypeMismatch, status); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" + << BSON("chainingAllowed" + << "no"))), + ExceptionFor<ErrorCodes::TypeMismatch>); } TEST(ReplSetConfig, ParseFailsWithNonBoolConfigServerField) { ReplSetConfig config; - ASSERT_NOT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "configsvr" - << "no"))); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "configsvr" + << "no")), + DBException); } TEST(ReplSetConfig, ParseFailsWithNonObjectSettingsField) { ReplSetConfig config; - Status status = config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" - << "none")); - ASSERT_EQUALS(ErrorCodes::TypeMismatch, status); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" + << "none")), + ExceptionFor<ErrorCodes::TypeMismatch>); } TEST(ReplSetConfig, ParseFailsWithGetLastErrorDefaultsFieldUnparseable) { ReplSetConfig config; - Status status = config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" - << BSON("getLastErrorDefaults" << BSON("fsync" - << "seven")))); - ASSERT_EQUALS(ErrorCodes::FailedToParse, status); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" + << BSON("getLastErrorDefaults" << BSON("fsync" + << "seven")))), + ExceptionFor<ErrorCodes::FailedToParse>); } TEST(ReplSetConfig, ParseFailsWithNonObjectGetLastErrorDefaultsField) { ReplSetConfig config; - Status status = config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" - << BSON("getLastErrorDefaults" - << "no"))); - ASSERT_EQUALS(ErrorCodes::TypeMismatch, status); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" + << BSON("getLastErrorDefaults" + << "no"))), + ExceptionFor<ErrorCodes::TypeMismatch>); } TEST(ReplSetConfig, ParseFailsWithNonObjectGetLastErrorModesField) { ReplSetConfig config; - Status status = config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" - << BSON("getLastErrorModes" - << "no"))); - ASSERT_EQUALS(ErrorCodes::TypeMismatch, status); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" + << BSON("getLastErrorModes" + << "no"))), + ExceptionFor<ErrorCodes::TypeMismatch>); } TEST(ReplSetConfig, ParseFailsWithDuplicateGetLastErrorModesField) { ReplSetConfig config; - Status status = config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "tags" - << BSON("tag" - << "yes"))) - << "settings" - << BSON("getLastErrorModes" - << BSON("one" << BSON("tag" << 1) << "one" - << BSON("tag" << 1))))); - ASSERT_EQUALS(51001, status.code()); + ASSERT_THROWS_CODE( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "tags" + << BSON("tag" + << "yes"))) + << "settings" + << BSON("getLastErrorModes" + << BSON("one" << BSON("tag" << 1) << "one" + << BSON("tag" << 1))))), + DBException, + 51001); } TEST(ReplSetConfig, ParseFailsWithNonObjectGetLastErrorModesEntryField) { ReplSetConfig config; - Status status = - config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "tags" - << BSON("tag" - << "yes"))) - << "settings" << BSON("getLastErrorModes" << BSON("one" << 1)))); - ASSERT_EQUALS(ErrorCodes::TypeMismatch, status); + ASSERT_THROWS( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "tags" + << BSON("tag" + << "yes"))) + << "settings" << BSON("getLastErrorModes" << BSON("one" << 1)))), + ExceptionFor<ErrorCodes::TypeMismatch>); } TEST(ReplSetConfig, ParseFailsWithNonNumericGetLastErrorModesConstraintValue) { ReplSetConfig config; - Status status = - config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "tags" - << BSON("tag" - << "yes"))) - << "settings" - << BSON("getLastErrorModes" << BSON("one" << BSON("tag" - << "no"))))); - ASSERT_EQUALS(ErrorCodes::TypeMismatch, status); + ASSERT_THROWS( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "tags" + << BSON("tag" + << "yes"))) + << "settings" + << BSON("getLastErrorModes" << BSON("one" << BSON("tag" + << "no"))))), + ExceptionFor<ErrorCodes::TypeMismatch>); } TEST(ReplSetConfig, ParseFailsWithNegativeGetLastErrorModesConstraintValue) { ReplSetConfig config; - Status status = - config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "tags" - << BSON("tag" - << "yes"))) - << "settings" - << BSON("getLastErrorModes" << BSON("one" << BSON("tag" << -1))))); - ASSERT_EQUALS(ErrorCodes::BadValue, status); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "tags" + << BSON("tag" + << "yes"))) + << "settings" + << BSON("getLastErrorModes" + << BSON("one" << BSON("tag" << -1))))), + ExceptionFor<ErrorCodes::BadValue>); } TEST(ReplSetConfig, ParseFailsWithNonExistentGetLastErrorModesConstraintTag) { ReplSetConfig config; - Status status = - config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "tags" - << BSON("tag" - << "yes"))) - << "settings" - << BSON("getLastErrorModes" << BSON("one" << BSON("tag2" << 1))))); - ASSERT_EQUALS(ErrorCodes::NoSuchKey, status); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "tags" + << BSON("tag" + << "yes"))) + << "settings" + << BSON("getLastErrorModes" + << BSON("one" << BSON("tag2" << 1))))), + ExceptionFor<ErrorCodes::NoSuchKey>); } TEST(ReplSetConfig, ParseFailsWithRepairField) { ReplSetConfig config; - Status status = config.initialize(BSON("_id" - << "rs0" - << "repaired" << true << "version" << 1 - << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")))); - ASSERT_EQUALS(ErrorCodes::RepairedReplicaSetNode, status); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "repaired" << true << "version" << 1 + << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")))), + ExceptionFor<ErrorCodes::RepairedReplicaSetNode>); } TEST(ReplSetConfig, ParseFailsWithBadProtocolVersion) { ReplSetConfig config; - ASSERT_NOT_OK(config.initialize(BSON("_id" - << "rs0" - << "protocolVersion" << 3 << "version" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345") - << BSON("_id" << 1 << "host" - << "localhost:54321"))))); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "protocolVersion" << 3 << "version" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345") + << BSON("_id" << 1 << "host" + << "localhost:54321")))), + DBException); } TEST(ReplSetConfig, ParseFailsWithProtocolVersion0) { ReplSetConfig config; - ASSERT_NOT_OK(config.initialize(BSON("_id" - << "rs0" - << "protocolVersion" << 0 << "version" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345") - << BSON("_id" << 1 << "host" - << "localhost:54321"))))); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "protocolVersion" << 0 << "version" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345") + << BSON("_id" << 1 << "host" + << "localhost:54321")))), + DBException); } TEST(ReplSetConfig, ValidateFailsWithDuplicateMemberId) { - ReplSetConfig config; - Status status = config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345") - << BSON("_id" << 0 << "host" - << "someoneelse:12345")))); - ASSERT_OK(status); - - status = config.validate(); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345") + << BSON("_id" << 0 << "host" + << "someoneelse:12345"))))); + auto status = config.validate(); ASSERT_EQUALS(ErrorCodes::BadValue, status); } TEST(ReplSetConfig, InitializeFailsWithInvalidMember) { ReplSetConfig config; - ASSERT_NOT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "hidden" << true))))); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "hidden" << true)))), + DBException); } TEST(ReplSetConfig, ChainingAllowedField) { - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" << BSON("chainingAllowed" << true)))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" << BSON("chainingAllowed" << true)))); ASSERT_OK(config.validate()); ASSERT_TRUE(config.isChainingAllowed()); - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" << BSON("chainingAllowed" << false)))); + config = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" << BSON("chainingAllowed" << false))); ASSERT_OK(config.validate()); ASSERT_FALSE(config.isChainingAllowed()); } TEST(ReplSetConfig, ConfigServerField) { - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "protocolVersion" << 1 << "version" << 1 << "configsvr" - << true << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "protocolVersion" << 1 << "version" << 1 << "configsvr" << true + << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345"))))); ASSERT_TRUE(config.getConfigServer()); // When the field is true it should be serialized. BSONObj configBSON = config.toBSON(); @@ -858,12 +867,12 @@ TEST(ReplSetConfig, ConfigServerField) { ASSERT_TRUE(configBSON.getField("configsvr").boolean()); ReplSetConfig config2; - ASSERT_OK(config2.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "configsvr" - << false << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); + config2 = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "configsvr" + << false << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")))); ASSERT_FALSE(config2.getConfigServer()); // When the field is false it should not be serialized. configBSON = config2.toBSON(); @@ -887,14 +896,14 @@ TEST(ReplSetConfig, SetNewlyAddedFieldForMemberConfig) { // Set the flag back to false after this test exits. ON_BLOCK_EXIT([] { enableAutomaticReconfig = false; }); - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "n1:1") - << BSON("_id" << 2 << "host" - << "n2:1"))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "n1:1") + << BSON("_id" << 2 << "host" + << "n2:1"))))); // The member should have its 'newlyAdded' field set to false by default. ASSERT_FALSE(config.findMemberByID(1)->isNewlyAdded()); @@ -910,16 +919,18 @@ TEST(ReplSetConfig, SetNewlyAddedFieldForMemberConfig) { ASSERT_EQ(modeIt->getMinCount(), 2); } - config.addNewlyAddedFieldForMember(MemberId(1)); + auto mutableConfig = config.getMutable(); + mutableConfig.addNewlyAddedFieldForMember(MemberId(1)); + ReplSetConfig newConfig(std::move(mutableConfig)); - ASSERT_TRUE(config.findMemberByID(1)->isNewlyAdded()); - ASSERT_EQ(1, config.getTotalVotingMembers()); - ASSERT_EQ(1, config.getMajorityVoteCount()); - ASSERT_EQ(1, config.getWriteMajority()); - ASSERT_EQ(1, config.getWritableVotingMembersCount()); + ASSERT_TRUE(newConfig.findMemberByID(1)->isNewlyAdded()); + ASSERT_EQ(1, newConfig.getTotalVotingMembers()); + ASSERT_EQ(1, newConfig.getMajorityVoteCount()); + ASSERT_EQ(1, newConfig.getWriteMajority()); + ASSERT_EQ(1, newConfig.getWritableVotingMembersCount()); { - auto modeSW = config.findCustomWriteMode("$majority"); + auto modeSW = newConfig.findCustomWriteMode("$majority"); ASSERT(modeSW.isOK()); auto modeIt = modeSW.getValue().constraintsBegin(); ASSERT_EQ(modeIt->getMinCount(), 1); @@ -932,15 +943,15 @@ TEST(ReplSetConfig, RemoveNewlyAddedFieldForMemberConfig) { // Set the flag back to false after this test exits. ON_BLOCK_EXIT([] { enableAutomaticReconfig = false; }); - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "n1:1" - << "newlyAdded" << true) - << BSON("_id" << 2 << "host" - << "n2:1"))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "n1:1" + << "newlyAdded" << true) + << BSON("_id" << 2 << "host" + << "n2:1"))))); ASSERT_TRUE(config.findMemberByID(1)->isNewlyAdded()); @@ -956,16 +967,18 @@ TEST(ReplSetConfig, RemoveNewlyAddedFieldForMemberConfig) { ASSERT_EQ(modeIt->getMinCount(), 1); } - config.removeNewlyAddedFieldForMember(MemberId(1)); + auto mutableConfig = config.getMutable(); + mutableConfig.removeNewlyAddedFieldForMember(MemberId(1)); + ReplSetConfig newConfig(std::move(mutableConfig)); - ASSERT_FALSE(config.findMemberByID(1)->isNewlyAdded()); - ASSERT_EQ(2, config.getTotalVotingMembers()); - ASSERT_EQ(2, config.getMajorityVoteCount()); - ASSERT_EQ(2, config.getWriteMajority()); - ASSERT_EQ(2, config.getWritableVotingMembersCount()); + ASSERT_FALSE(newConfig.findMemberByID(1)->isNewlyAdded()); + ASSERT_EQ(2, newConfig.getTotalVotingMembers()); + ASSERT_EQ(2, newConfig.getMajorityVoteCount()); + ASSERT_EQ(2, newConfig.getWriteMajority()); + ASSERT_EQ(2, newConfig.getWritableVotingMembersCount()); { - auto modeSW = config.findCustomWriteMode("$majority"); + auto modeSW = newConfig.findCustomWriteMode("$majority"); ASSERT(modeSW.isOK()); auto modeIt = modeSW.getValue().constraintsBegin(); ASSERT_EQ(modeIt->getMinCount(), 2); @@ -978,13 +991,13 @@ TEST(ReplSetConfig, ParsingNewlyAddedSetsFieldToTrueCorrectly) { // Set the flag back to false after this test exits. ON_BLOCK_EXIT([] { enableAutomaticReconfig = false; }); - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "localhost:12345" - << "newlyAdded" << true))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "localhost:12345" + << "newlyAdded" << true))))); // The member should have its 'newlyAdded' field set to true after parsing. ASSERT_TRUE(config.findMemberByID(1)->isNewlyAdded()); @@ -997,14 +1010,13 @@ TEST(ReplSetConfig, ParseFailsWithNewlyAddedSetToFalse) { ON_BLOCK_EXIT([] { enableAutomaticReconfig = false; }); ReplSetConfig config; - Status status = config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "localhost:12345" - << "newlyAdded" << false)))); - - ASSERT_EQUALS(ErrorCodes::InvalidReplicaSetConfig, status); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "localhost:12345" + << "newlyAdded" << false)))), + ExceptionFor<ErrorCodes::InvalidReplicaSetConfig>); } TEST(ReplSetConfig, NodeWithNewlyAddedFieldHasVotesZero) { @@ -1014,18 +1026,18 @@ TEST(ReplSetConfig, NodeWithNewlyAddedFieldHasVotesZero) { ON_BLOCK_EXIT([] { enableAutomaticReconfig = false; }); // Create a config for a three-node set with one arbiter and one node with 'newlyAdded: true'. - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "n1:1" - << "newlyAdded" << true) - << BSON("_id" << 2 << "host" - << "n2:1") - << BSON("_id" << 3 << "host" - << "n3:1" - << "arbiterOnly" << true))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "n1:1" + << "newlyAdded" << true) + << BSON("_id" << 2 << "host" + << "n2:1") + << BSON("_id" << 3 << "host" + << "n3:1" + << "arbiterOnly" << true))))); // Verify that the member had its 'newlyAdded' field set to true after parsing. ASSERT_TRUE(config.findMemberByID(1)->isNewlyAdded()); @@ -1046,32 +1058,33 @@ TEST(ReplSetConfig, ToBSONWithoutNewlyAdded) { ON_BLOCK_EXIT([] { enableAutomaticReconfig = false; }); // Create a config for a three-node set with one arbiter and one node with 'newlyAdded: true'. - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "n1:1" - << "newlyAdded" << true) - << BSON("_id" << 2 << "host" - << "n2:1") - << BSON("_id" << 3 << "host" - << "n3:1" - << "arbiterOnly" << true))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "n1:1" + << "newlyAdded" << true) + << BSON("_id" << 2 << "host" + << "n2:1") + << BSON("_id" << 3 << "host" + << "n3:1" + << "arbiterOnly" << true))))); // same config, without "newlyAdded: true" ReplSetConfig config_expected; - ASSERT_OK( - config_expected.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "n1:1") - << BSON("_id" << 2 << "host" - << "n2:1") - << BSON("_id" << 3 << "host" - << "n3:1" - << "arbiterOnly" << true))))); + + config_expected = + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "n1:1") + << BSON("_id" << 2 << "host" + << "n2:1") + << BSON("_id" << 3 << "host" + << "n3:1" + << "arbiterOnly" << true)))); // Sanity check; these objects should not be equal with ordinary serialization, because of the // newlyAdded field. ASSERT_BSONOBJ_NE(config_expected.toBSON(), config.toBSON()); @@ -1082,46 +1095,46 @@ TEST(ReplSetConfig, ToBSONWithoutNewlyAdded) { TEST(ReplSetConfig, ConfigServerFieldDefaults) { serverGlobalParams.clusterRole = ClusterRole::None; - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "protocolVersion" << 1 << "version" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "protocolVersion" << 1 << "version" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345"))))); ASSERT_FALSE(config.getConfigServer()); // Default false configsvr field should not be serialized. BSONObj configBSON = config.toBSON(); ASSERT_FALSE(configBSON.hasField("configsvr")); - ReplSetConfig config2; - ASSERT_OK( - config2.initializeForInitiate(BSON("_id" - << "rs0" - << "protocolVersion" << 1 << "version" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))), - OID::gen())); + ReplSetConfig config2( + ReplSetConfig::parseForInitiate(BSON("_id" + << "rs0" + << "protocolVersion" << 1 << "version" << 1 + << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345"))), + OID::gen())); ASSERT_FALSE(config2.getConfigServer()); serverGlobalParams.clusterRole = ClusterRole::ConfigServer; ON_BLOCK_EXIT([&] { serverGlobalParams.clusterRole = ClusterRole::None; }); ReplSetConfig config3; - ASSERT_OK(config3.initialize(BSON("_id" - << "rs0" - << "protocolVersion" << 1 << "version" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); + config3 = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "protocolVersion" << 1 << "version" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")))); ASSERT_FALSE(config3.getConfigServer()); - ReplSetConfig config4; - ASSERT_OK( - config4.initializeForInitiate(BSON("_id" - << "rs0" - << "protocolVersion" << 1 << "version" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))), - OID::gen())); + ReplSetConfig config4( + ReplSetConfig::parseForInitiate(BSON("_id" + << "rs0" + << "protocolVersion" << 1 << "version" << 1 + << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345"))), + OID::gen())); ASSERT_TRUE(config4.getConfigServer()); // Default true configsvr field should be serialized (even though it wasn't included // originally). @@ -1131,130 +1144,134 @@ TEST(ReplSetConfig, ConfigServerFieldDefaults) { } TEST(ReplSetConfig, HeartbeatIntervalField) { - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" << BSON("heartbeatIntervalMillis" << 5000)))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" << BSON("heartbeatIntervalMillis" << 5000)))); ASSERT_OK(config.validate()); ASSERT_EQUALS(Seconds(5), config.getHeartbeatInterval()); - ASSERT_NOT_OK( - config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" << BSON("heartbeatIntervalMillis" << -5000)))); + ASSERT_THROWS( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" << BSON("heartbeatIntervalMillis" << -5000))), + DBException); } // This test covers the "exact" behavior of all the smallExactInt fields. TEST(ReplSetConfig, DecimalHeartbeatIntervalField) { - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" << BSON("heartbeatIntervalMillis" << 5000.0)))); - - ASSERT_NOT_OK( - config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" << BSON("heartbeatIntervalMillis" << 5000.1)))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" << BSON("heartbeatIntervalMillis" << 5000.0)))); + + ASSERT_THROWS( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" << BSON("heartbeatIntervalMillis" << 5000.1))), + DBException); } TEST(ReplSetConfig, ElectionTimeoutField) { - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" << BSON("electionTimeoutMillis" << 20)))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" << BSON("electionTimeoutMillis" << 20)))); ASSERT_OK(config.validate()); ASSERT_EQUALS(Milliseconds(20), config.getElectionTimeoutPeriod()); - auto status = config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" << BSON("electionTimeoutMillis" << -20))); - ASSERT_NOT_OK(status); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" << BSON("electionTimeoutMillis" << -20))), + DBException); } TEST(ReplSetConfig, HeartbeatTimeoutField) { - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" << BSON("heartbeatTimeoutSecs" << 20)))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" << BSON("heartbeatTimeoutSecs" << 20)))); ASSERT_OK(config.validate()); ASSERT_EQUALS(Seconds(20), config.getHeartbeatTimeoutPeriod()); - auto status = config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" << BSON("heartbeatTimeoutSecs" << -20))); - ASSERT_NOT_OK(status); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" << BSON("heartbeatTimeoutSecs" << -20))), + DBException); } TEST(ReplSetConfig, GleDefaultField) { - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" - << BSON("getLastErrorDefaults" << BSON("w" - << "majority"))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" + << BSON("getLastErrorDefaults" << BSON("w" + << "majority"))))); ASSERT_OK(config.validate()); ASSERT_EQUALS("majority", config.getDefaultWriteConcern().wMode); - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" - << BSON("getLastErrorDefaults" << BSON("w" - << "frim"))))); + config = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" + << BSON("getLastErrorDefaults" << BSON("w" + << "frim")))); ASSERT_EQUALS(ErrorCodes::BadValue, config.validate()); // Test that default write concern must have at least one member. - ASSERT_NOT_OK( - config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" << BSON("getLastErrorDefaults" << BSON("w" << 0))))); - - ASSERT_OK( - config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "tags" - << BSON("a" - << "v"))) - << "settings" - << BSON("getLastErrorDefaults" << BSON("w" - << "frim") - << "getLastErrorModes" - << BSON("frim" << BSON("a" << 1)))))); + ASSERT_THROWS( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" << BSON("getLastErrorDefaults" << BSON("w" << 0)))), + DBException); + + + config = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "tags" + << BSON("a" + << "v"))) + << "settings" + << BSON("getLastErrorDefaults" + << BSON("w" + << "frim") + << "getLastErrorModes" + << BSON("frim" << BSON("a" << 1))))); ASSERT_OK(config.validate()); ASSERT_EQUALS("frim", config.getDefaultWriteConcern().wMode); ASSERT_OK(config.findCustomWriteMode("frim").getStatus()); @@ -1333,35 +1350,35 @@ bool operator==(const ReplSetConfig& a, const ReplSetConfig& b) { TEST(ReplSetConfig, toBSONRoundTripAbility) { ReplSetConfig configA; ReplSetConfig configB; - ASSERT_OK(configA.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" - << BSON("heartbeatIntervalMillis" - << 5000 << "heartbeatTimeoutSecs" << 20 - << "replicaSetId" << OID::gen())))); - ASSERT_OK(configB.initialize(configA.toBSON())); + configA = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" + << BSON("heartbeatIntervalMillis" + << 5000 << "heartbeatTimeoutSecs" << 20 + << "replicaSetId" << OID::gen()))); + configB = ReplSetConfig::parse(configA.toBSON()); ASSERT_TRUE(configA == configB); } TEST(ReplSetConfig, toBSONRoundTripAbilityWithHorizon) { ReplSetConfig configA; ReplSetConfig configB; - ASSERT_OK(configA.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "horizons" - << BSON("horizon" - << "example.com:42"))) - << "settings" - << BSON("heartbeatIntervalMillis" - << 5000 << "heartbeatTimeoutSecs" << 20 - << "replicaSetId" << OID::gen())))); - ASSERT_OK(configB.initialize(configA.toBSON())); + configA = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "horizons" + << BSON("horizon" + << "example.com:42"))) + << "settings" + << BSON("heartbeatIntervalMillis" + << 5000 << "heartbeatTimeoutSecs" << 20 + << "replicaSetId" << OID::gen()))); + configB = ReplSetConfig::parse(configA.toBSON()); ASSERT_TRUE(configA == configB); } @@ -1373,7 +1390,7 @@ TEST(ReplSetConfig, toBSONRoundTripAbilityLarge) { ReplSetConfig configA; ReplSetConfig configB; - ASSERT_OK(configA.initialize(BSON( + configA = ReplSetConfig::parse(BSON( "_id" << "asdf" << "version" << 9 << "writeConcernMajorityJournalDefault" << true << "members" @@ -1405,33 +1422,35 @@ TEST(ReplSetConfig, toBSONRoundTripAbilityLarge) { << "majority") << "getLastErrorModes" << BSON("disks" << BSON("ssd" << 1 << "hdd" << 1) - << "coasts" << BSON("coast" << 2)))))); + << "coasts" << BSON("coast" << 2))))); BSONObj configObjA = configA.toBSON(); - ASSERT_OK(configB.initialize(configObjA)); + configB = ReplSetConfig::parse(configObjA); ASSERT_TRUE(configA == configB); } TEST(ReplSetConfig, toBSONRoundTripAbilityInvalid) { ReplSetConfig configA; ReplSetConfig configB; - ASSERT_NOT_OK(configA.initialize( - BSON("_id" - << "" - << "version" << -3 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "arbiterOnly" << true << "votes" << 0 << "priority" << 0) - << BSON("_id" << 0 << "host" - << "localhost:3828" - << "arbiterOnly" << false << "buildIndexes" << false - << "priority" << 2) - << BSON("_id" << 2 << "host" - << "localhost:3828" - << "votes" << 0 << "priority" << 0)) - << "settings" - << BSON("heartbeatIntervalMillis" << -5000 << "heartbeatTimeoutSecs" << 20 - << "electionTimeoutMillis" << 2)))); - ASSERT_OK(configB.initialize(configA.toBSON())); + ASSERT_THROWS( + ReplSetConfig::parse(BSON( + "_id" + << "" + << "version" << -3 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "arbiterOnly" << true << "votes" << 0 << "priority" << 0) + << BSON("_id" << 0 << "host" + << "localhost:3828" + << "arbiterOnly" << false << "buildIndexes" << false + << "priority" << 2) + << BSON("_id" << 2 << "host" + << "localhost:3828" + << "votes" << 0 << "priority" << 0)) + << "settings" + << BSON("heartbeatIntervalMillis" << -5000 << "heartbeatTimeoutSecs" << 20 + << "electionTimeoutMillis" << 2))), + DBException); + configB = ReplSetConfig::parse(configA.toBSON()); ASSERT_NOT_OK(configA.validate()); ASSERT_NOT_OK(configB.validate()); ASSERT_TRUE(configA == configB); @@ -1439,7 +1458,7 @@ TEST(ReplSetConfig, toBSONRoundTripAbilityInvalid) { TEST(ReplSetConfig, CheckIfWriteConcernCanBeSatisfied) { ReplSetConfig configA; - ASSERT_OK(configA.initialize(BSON( + configA = ReplSetConfig::parse(BSON( "_id" << "rs0" << "version" << 1 << "protocolVersion" << 1 << "members" @@ -1484,7 +1503,7 @@ TEST(ReplSetConfig, CheckIfWriteConcernCanBeSatisfied) { << "settings" << BSON("getLastErrorModes" << BSON( "valid" << BSON("dc" << 2 << "rack" << 3) << "invalidNotEnoughValues" - << BSON("dc" << 3) << "invalidNotEnoughNodes" << BSON("rack" << 6)))))); + << BSON("dc" << 3) << "invalidNotEnoughNodes" << BSON("rack" << 6))))); WriteConcernOptions validNumberWC; validNumberWC.wNumNodes = 5; @@ -1523,8 +1542,8 @@ TEST(ReplSetConfig, CheckMaximumNodesOkay) { ReplSetConfig configA; ReplSetConfig configB; const int memberCount = 50; - ASSERT_OK(configA.initialize(createConfigDoc(memberCount))); - ASSERT_OK(configB.initialize(configA.toBSON())); + configA = ReplSetConfig::parse(createConfigDoc(memberCount)); + configB = ReplSetConfig::parse(configA.toBSON()); ASSERT_OK(configA.validate()); ASSERT_OK(configB.validate()); ASSERT_TRUE(configA == configB); @@ -1534,8 +1553,8 @@ TEST(ReplSetConfig, CheckBeyondMaximumNodesFailsValidate) { ReplSetConfig configA; ReplSetConfig configB; const int memberCount = 51; - ASSERT_OK(configA.initialize(createConfigDoc(memberCount))); - ASSERT_OK(configB.initialize(configA.toBSON())); + configA = ReplSetConfig::parse(createConfigDoc(memberCount)); + configB = ReplSetConfig::parse(configA.toBSON()); ASSERT_NOT_OK(configA.validate()); ASSERT_NOT_OK(configB.validate()); ASSERT_TRUE(configA == configB); @@ -1543,15 +1562,15 @@ TEST(ReplSetConfig, CheckBeyondMaximumNodesFailsValidate) { TEST(ReplSetConfig, CheckConfigServerCantHaveArbiters) { ReplSetConfig configA; - ASSERT_OK(configA.initialize(BSON("_id" - << "rs0" - << "protocolVersion" << 1 << "version" << 1 << "configsvr" - << true << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345") - << BSON("_id" << 1 << "host" - << "localhost:54321" - << "arbiterOnly" << true))))); + configA = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "protocolVersion" << 1 << "version" << 1 << "configsvr" + << true << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345") + << BSON("_id" << 1 << "host" + << "localhost:54321" + << "arbiterOnly" << true)))); Status status = configA.validate(); ASSERT_EQUALS(ErrorCodes::BadValue, status); ASSERT_STRING_CONTAINS(status.reason(), "Arbiters are not allowed"); @@ -1559,16 +1578,16 @@ TEST(ReplSetConfig, CheckConfigServerCantHaveArbiters) { TEST(ReplSetConfig, CheckConfigServerMustBuildIndexes) { ReplSetConfig configA; - ASSERT_OK(configA.initialize(BSON("_id" - << "rs0" - << "protocolVersion" << 1 << "version" << 1 << "configsvr" - << true << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345") - << BSON("_id" << 1 << "host" - << "localhost:54321" - << "priority" << 0 - << "buildIndexes" << false))))); + configA = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "protocolVersion" << 1 << "version" << 1 << "configsvr" + << true << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345") + << BSON("_id" << 1 << "host" + << "localhost:54321" + << "priority" << 0 + << "buildIndexes" << false)))); Status status = configA.validate(); ASSERT_EQUALS(ErrorCodes::BadValue, status); ASSERT_STRING_CONTAINS(status.reason(), "must build indexes"); @@ -1576,16 +1595,16 @@ TEST(ReplSetConfig, CheckConfigServerMustBuildIndexes) { TEST(ReplSetConfig, CheckConfigServerCantHaveSlaveDelay) { ReplSetConfig configA; - ASSERT_OK(configA.initialize(BSON("_id" - << "rs0" - << "protocolVersion" << 1 << "version" << 1 << "configsvr" - << true << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345") - << BSON("_id" << 1 << "host" - << "localhost:54321" - << "priority" << 0 << "slaveDelay" - << 3))))); + configA = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "protocolVersion" << 1 << "version" << 1 << "configsvr" + << true << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345") + << BSON("_id" << 1 << "host" + << "localhost:54321" + << "priority" << 0 + << "slaveDelay" << 3)))); Status status = configA.validate(); ASSERT_EQUALS(ErrorCodes::BadValue, status); ASSERT_STRING_CONTAINS(status.reason(), "cannot have a non-zero slaveDelay"); @@ -1595,15 +1614,15 @@ TEST(ReplSetConfig, CheckConfigServerMustHaveTrueForWriteConcernMajorityJournalD serverGlobalParams.clusterRole = ClusterRole::ConfigServer; ON_BLOCK_EXIT([&] { serverGlobalParams.clusterRole = ClusterRole::None; }); ReplSetConfig configA; - ASSERT_OK(configA.initialize(BSON("_id" - << "rs0" - << "protocolVersion" << 1 << "version" << 1 << "configsvr" - << true << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345") - << BSON("_id" << 1 << "host" - << "localhost:54321")) - << "writeConcernMajorityJournalDefault" << false))); + configA = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "protocolVersion" << 1 << "version" << 1 << "configsvr" + << true << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345") + << BSON("_id" << 1 << "host" + << "localhost:54321")) + << "writeConcernMajorityJournalDefault" << false)); Status status = configA.validate(); ASSERT_EQUALS(ErrorCodes::BadValue, status); ASSERT_STRING_CONTAINS(status.reason(), " must be true in replica set configurations being "); @@ -1611,25 +1630,25 @@ TEST(ReplSetConfig, CheckConfigServerMustHaveTrueForWriteConcernMajorityJournalD TEST(ReplSetConfig, GetPriorityTakeoverDelay) { ReplSetConfig configA; - ASSERT_OK(configA.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "priority" << 1) - << BSON("_id" << 1 << "host" - << "localhost:54321" - << "priority" << 2) - << BSON("_id" << 2 << "host" - << "localhost:5321" - << "priority" << 3) - << BSON("_id" << 3 << "host" - << "localhost:5421" - << "priority" << 4) - << BSON("_id" << 4 << "host" - << "localhost:5431" - << "priority" << 5)) - << "settings" << BSON("electionTimeoutMillis" << 1000)))); + configA = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "priority" << 1) + << BSON("_id" << 1 << "host" + << "localhost:54321" + << "priority" << 2) + << BSON("_id" << 2 << "host" + << "localhost:5321" + << "priority" << 3) + << BSON("_id" << 3 << "host" + << "localhost:5421" + << "priority" << 4) + << BSON("_id" << 4 << "host" + << "localhost:5431" + << "priority" << 5)) + << "settings" << BSON("electionTimeoutMillis" << 1000))); ASSERT_OK(configA.validate()); ASSERT_EQUALS(Milliseconds(5000), configA.getPriorityTakeoverDelay(0)); ASSERT_EQUALS(Milliseconds(4000), configA.getPriorityTakeoverDelay(1)); @@ -1638,25 +1657,25 @@ TEST(ReplSetConfig, GetPriorityTakeoverDelay) { ASSERT_EQUALS(Milliseconds(1000), configA.getPriorityTakeoverDelay(4)); ReplSetConfig configB; - ASSERT_OK(configB.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "priority" << 1) - << BSON("_id" << 1 << "host" - << "localhost:54321" - << "priority" << 2) - << BSON("_id" << 2 << "host" - << "localhost:5321" - << "priority" << 2) - << BSON("_id" << 3 << "host" - << "localhost:5421" - << "priority" << 3) - << BSON("_id" << 4 << "host" - << "localhost:5431" - << "priority" << 3)) - << "settings" << BSON("electionTimeoutMillis" << 1000)))); + configB = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "priority" << 1) + << BSON("_id" << 1 << "host" + << "localhost:54321" + << "priority" << 2) + << BSON("_id" << 2 << "host" + << "localhost:5321" + << "priority" << 2) + << BSON("_id" << 3 << "host" + << "localhost:5421" + << "priority" << 3) + << BSON("_id" << 4 << "host" + << "localhost:5431" + << "priority" << 3)) + << "settings" << BSON("electionTimeoutMillis" << 1000))); ASSERT_OK(configB.validate()); ASSERT_EQUALS(Milliseconds(5000), configB.getPriorityTakeoverDelay(0)); ASSERT_EQUALS(Milliseconds(3000), configB.getPriorityTakeoverDelay(1)); @@ -1666,40 +1685,40 @@ TEST(ReplSetConfig, GetPriorityTakeoverDelay) { } TEST(ReplSetConfig, GetCatchUpTakeoverDelay) { - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" << BSON("catchUpTakeoverDelayMillis" << 5000)))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" << BSON("catchUpTakeoverDelayMillis" << 5000)))); ASSERT_OK(config.validate()); ASSERT_EQUALS(Milliseconds(5000), config.getCatchUpTakeoverDelay()); - Status status = - config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "settings" << BSON("catchUpTakeoverDelayMillis" << -5000))); - ASSERT_NOT_OK(status); + ASSERT_THROWS( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "settings" << BSON("catchUpTakeoverDelayMillis" << -5000))), + DBException); } TEST(ReplSetConfig, GetCatchUpTakeoverDelayDefault) { - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "priority" << 1) - << BSON("_id" << 1 << "host" - << "localhost:54321" - << "priority" << 2) - << BSON("_id" << 2 << "host" - << "localhost:5321" - << "priority" << 3))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "priority" << 1) + << BSON("_id" << 1 << "host" + << "localhost:54321" + << "priority" << 2) + << BSON("_id" << 2 << "host" + << "localhost:5321" + << "priority" << 3))))); ASSERT_OK(config.validate()); ASSERT_EQUALS(Milliseconds(30000), config.getCatchUpTakeoverDelay()); } @@ -1708,61 +1727,61 @@ TEST(ReplSetConfig, ConfirmDefaultValuesOfAndAbilityToSetWriteConcernMajorityJou ReplSetConfig config; // PV1, should default to true. - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "protocolVersion" << 1 << "version" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345"))))); + config = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "protocolVersion" << 1 << "version" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")))); ASSERT_OK(config.validate()); ASSERT_TRUE(config.getWriteConcernMajorityShouldJournal()); ASSERT_TRUE(config.toBSON().hasField("writeConcernMajorityJournalDefault")); // Should be able to set it false in PV1. - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "protocolVersion" << 1 << "version" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345")) - << "writeConcernMajorityJournalDefault" << false))); + config = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "protocolVersion" << 1 << "version" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345")) + << "writeConcernMajorityJournalDefault" << false)); ASSERT_OK(config.validate()); ASSERT_FALSE(config.getWriteConcernMajorityShouldJournal()); ASSERT_TRUE(config.toBSON().hasField("writeConcernMajorityJournalDefault")); } TEST(ReplSetConfig, HorizonConsistency) { - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "protocolVersion" << 1 << "version" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "protocolVersion" << 1 << "version" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "horizons" + << BSON("alpha" + << "a.host:42" + << "beta" + << "a.host2:43" + << "gamma" + << "a.host3:44")) + << BSON("_id" << 1 << "host" + << "localhost:23456" + << "horizons" + << BSON("alpha" + << "b.host:42" + << "gamma" + << "b.host3:44")) + << BSON("_id" << 2 << "host" + << "localhost:34567" << "horizons" << BSON("alpha" - << "a.host:42" + << "c.host:42" << "beta" - << "a.host2:43" + << "c.host1:42" << "gamma" - << "a.host3:44")) - << BSON("_id" << 1 << "host" - << "localhost:23456" - << "horizons" - << BSON("alpha" - << "b.host:42" - << "gamma" - << "b.host3:44")) - << BSON("_id" << 2 << "host" - << "localhost:34567" - << "horizons" - << BSON("alpha" - << "c.host:42" - << "beta" - << "c.host1:42" - << "gamma" - << "c.host2:43" - << "delta" + << "c.host2:43" + << "delta" - << "c.host3:44"))) - << "writeConcernMajorityJournalDefault" << false))); + << "c.host3:44"))) + << "writeConcernMajorityJournalDefault" << false))); Status status = config.validate(); ASSERT_NOT_OK(status); @@ -1774,55 +1793,54 @@ TEST(ReplSetConfig, HorizonConsistency) { // Within-member duplicates are detected by a different piece of code, first, // in the member-config code path. - status = config.initialize(BSON("_id" - << "rs0" - << "protocolVersion" << 1 << "version" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "same1" - << "horizons" - << BSON("alpha" - << "a.host:44" - << "beta" - << "a.host2:44" - << "gamma" - << "a.host3:44" - << "delta" - << "a.host4:45")) - << BSON("_id" << 1 << "host" - << "localhost:1" + config = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "protocolVersion" << 1 << "version" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "same1" << "horizons" << BSON("alpha" - << "same1" + << "a.host:44" << "beta" - << "b.host2:44" + << "a.host2:44" << "gamma" - << "b.host3:44" + << "a.host3:44" << "delta" - << "b.host4:44")) - << BSON("_id" << 2 << "host" - << "localhost:2" - << "horizons" - << BSON("alpha" - << "c.host1:44" - << "beta" - << "c.host2:44" - << "gamma" - << "c.host3:44" - << "delta" - << "same2")) - << BSON("_id" << 3 << "host" - << "localhost:3" - << "horizons" - << BSON("alpha" - << "same2" - << "beta" - << "d.host2:44" - << "gamma" - << "d.host3:44" - << "delta" - << "d.host4:44"))) - << "writeConcernMajorityJournalDefault" << false)); - ASSERT_OK(status) << " failing status was: " << status.reason(); + << "a.host4:45")) + << BSON("_id" << 1 << "host" + << "localhost:1" + << "horizons" + << BSON("alpha" + << "same1" + << "beta" + << "b.host2:44" + << "gamma" + << "b.host3:44" + << "delta" + << "b.host4:44")) + << BSON("_id" << 2 << "host" + << "localhost:2" + << "horizons" + << BSON("alpha" + << "c.host1:44" + << "beta" + << "c.host2:44" + << "gamma" + << "c.host3:44" + << "delta" + << "same2")) + << BSON("_id" << 3 << "host" + << "localhost:3" + << "horizons" + << BSON("alpha" + << "same2" + << "beta" + << "d.host2:44" + << "gamma" + << "d.host3:44" + << "delta" + << "d.host4:44"))) + << "writeConcernMajorityJournalDefault" << false)); status = config.validate(); ASSERT_NOT_OK(status); @@ -1843,87 +1861,90 @@ TEST(ReplSetConfig, ReplSetId) { // Cannot provide replica set ID in configuration document when initialized from // replSetInitiate, because it will not match the new one passed in. OID newReplSetId = OID::gen(); - auto status = - ReplSetConfig().initializeForInitiate(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "priority" << 1)) - << "settings" - << BSON("replicaSetId" << OID::gen())), - newReplSetId); - ASSERT_EQUALS(ErrorCodes::InvalidReplicaSetConfig, status); - ASSERT_STRING_CONTAINS(status.reason(), - "replica set configuration cannot contain 'replicaSetId' field when " - "called from replSetInitiate"); + ASSERT_THROWS_WITH_CHECK( + ReplSetConfig::parseForInitiate(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 + << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "priority" << 1)) + << "settings" << BSON("replicaSetId" << OID::gen())), + newReplSetId), + ExceptionFor<ErrorCodes::InvalidReplicaSetConfig>, + ([&](const DBException& ex) { + ASSERT_STRING_CONTAINS( + ex.what(), + "replica set configuration cannot contain 'replicaSetId' field when " + "called from replSetInitiate"); + })); // Cannot initiate with an empty ID. - ASSERT_NOT_OK( - ReplSetConfig().initializeForInitiate(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "priority" << 1))), - OID())); + ASSERT_THROWS( + ReplSetConfig::parseForInitiate(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 + << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "priority" << 1))), + OID()), + DBException); // Configuration created by replSetInitiate should use passed-in replica set ID - ReplSetConfig configInitiate; - ASSERT_OK( - configInitiate.initializeForInitiate(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 - << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "priority" << 1))), - newReplSetId)); + ReplSetConfig configInitiate( + ReplSetConfig::parseForInitiate(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 + << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "priority" << 1))), + newReplSetId)); ASSERT_OK(configInitiate.validate()); ASSERT_TRUE(configInitiate.hasReplicaSetId()); OID replicaSetId = configInitiate.getReplicaSetId(); ASSERT_EQ(newReplSetId, replicaSetId); // Configuration initialized from local database can contain ID. - ReplSetConfig configLocal; - ASSERT_OK(configLocal.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "priority" << 1)) - << "settings" << BSON("replicaSetId" << replicaSetId)))); + ReplSetConfig configLocal( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "priority" << 1)) + << "settings" << BSON("replicaSetId" << replicaSetId)))); ASSERT_OK(configLocal.validate()); ASSERT_TRUE(configLocal.hasReplicaSetId()); ASSERT_EQUALS(replicaSetId, configLocal.getReplicaSetId()); // When reconfiguring, we can provide a default ID if the configuration does not contain one. OID defaultReplicaSetId = OID::gen(); - ASSERT_OK(configLocal.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "priority" << 1))), - boost::none, - defaultReplicaSetId)); + configLocal = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "priority" << 1))), + boost::none, + defaultReplicaSetId); ASSERT_OK(configLocal.validate()); ASSERT_TRUE(configLocal.hasReplicaSetId()); ASSERT_EQUALS(defaultReplicaSetId, configLocal.getReplicaSetId()); // When reconfiguring, we can provide a default ID if the configuration contains a matching one. - ASSERT_OK( - configLocal.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "priority" << 1)) - << "settings" << BSON("replicaSetId" << defaultReplicaSetId)), - boost::none, - defaultReplicaSetId)); + + configLocal = + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "priority" << 1)) + << "settings" << BSON("replicaSetId" << defaultReplicaSetId)), + boost::none, + defaultReplicaSetId); ASSERT_OK(configLocal.validate()); ASSERT_TRUE(configLocal.hasReplicaSetId()); ASSERT_EQUALS(defaultReplicaSetId, configLocal.getReplicaSetId()); @@ -1931,38 +1952,42 @@ TEST(ReplSetConfig, ReplSetId) { // If the default config does not match the one in the BSON, the one passed-on should be used. // (note: this will be rejected by validateConfigForReconfig) OID bsonReplicaSetId = OID::gen(); - status = configLocal.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "priority" << 1)) - << "settings" << BSON("replicaSetId" << bsonReplicaSetId)), - boost::none, - defaultReplicaSetId); - ASSERT_OK(status); + configLocal = + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "priority" << 1)) + << "settings" << BSON("replicaSetId" << bsonReplicaSetId)), + boost::none, + defaultReplicaSetId); ASSERT_EQ(bsonReplicaSetId, configLocal.getReplicaSetId()); // 'replicaSetId' field cannot be explicitly null. - status = configLocal.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "priority" << 1)) - << "settings" << BSON("replicaSetId" << OID()))); - ASSERT_EQUALS(ErrorCodes::BadValue, status); - ASSERT_STRING_CONTAINS(status.reason(), "replicaSetId field value cannot be null"); + ASSERT_THROWS_WITH_CHECK( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "priority" << 1)) + << "settings" << BSON("replicaSetId" << OID()))), + ExceptionFor<ErrorCodes::BadValue>, + ([&](const DBException& ex) { + ASSERT_STRING_CONTAINS(ex.what(), "replicaSetId field value cannot be null"); + })); + // 'replicaSetId' field must be an OID. - status = configLocal.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "localhost:12345" - << "priority" << 1)) - << "settings" << BSON("replicaSetId" << 12345))); - ASSERT_EQUALS(ErrorCodes::TypeMismatch, status); + ASSERT_THROWS(ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "localhost:12345" + << "priority" << 1)) + << "settings" << BSON("replicaSetId" << 12345))), + ExceptionFor<ErrorCodes::TypeMismatch>); } TEST(ReplSetConfig, ConfigVersionAndTermComparison) { diff --git a/src/mongo/db/repl/repl_set_heartbeat_response.cpp b/src/mongo/db/repl/repl_set_heartbeat_response.cpp index 0dc2bc2eb45..138f6c84e1e 100644 --- a/src/mongo/db/repl/repl_set_heartbeat_response.cpp +++ b/src/mongo/db/repl/repl_set_heartbeat_response.cpp @@ -252,7 +252,12 @@ Status ReplSetHeartbeatResponse::initialize(const BSONObj& doc, long long term) } _configSet = true; - return _config.initialize(rsConfigElement.Obj()); + try { + _config = ReplSetConfig::parse(rsConfigElement.Obj()); + } catch (const DBException& e) { + return e.toStatus(); + } + return Status::OK(); } MemberState ReplSetHeartbeatResponse::getState() const { diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp index ac24bd2d1bf..ebde2673416 100644 --- a/src/mongo/db/repl/replication_coordinator_impl.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl.cpp @@ -497,8 +497,10 @@ bool ReplicationCoordinatorImpl::_startLoadLocalConfig(OperationContext* opCtx) return true; } ReplSetConfig localConfig; - status = localConfig.initialize(cfg.getValue()); - if (!status.isOK()) { + try { + localConfig = ReplSetConfig::parse(cfg.getValue()); + } catch (const DBException& e) { + auto status = e.toStatus(); if (status.code() == ErrorCodes::RepairedReplicaSetNode) { LOGV2_FATAL_NOTRACE( 50923, @@ -1183,9 +1185,9 @@ void ReplicationCoordinatorImpl::signalDrainComplete(OperationContext* opCtx, return {ErrorCodes::ConfigurationInProgress, "reconfig on step up was preempted by another reconfig"}; } - auto config = oldConfig; + auto config = oldConfig.getMutable(); config.setConfigTerm(primaryTerm); - return config; + return ReplSetConfig(std::move(config)); }; LOGV2(4508103, "Increment the config term via reconfig"); auto reconfigStatus = doReplSetReconfig(opCtx, getNewConfig, true /* force */); @@ -3218,10 +3220,10 @@ Status ReplicationCoordinatorImpl::processReplSetReconfig(OperationContext* opCt // When initializing a new config through the replSetReconfig command, ignore the term // field passed in through its args. Instead, use this node's term. - const Status status = - newConfig.initialize(args.newConfigObj, term, oldConfig.getReplicaSetId()); - - if (!status.isOK()) { + try { + newConfig = ReplSetConfig::parse(args.newConfigObj, term, oldConfig.getReplicaSetId()); + } catch (const DBException& e) { + auto status = e.toStatus(); LOGV2_ERROR(21418, "replSetReconfig got {error} while parsing {newConfig}", "replSetReconfig error parsing new config", @@ -3247,11 +3249,13 @@ Status ReplicationCoordinatorImpl::processReplSetReconfig(OperationContext* opCt // Increase the config version for force reconfig. auto version = std::max(oldConfig.getConfigVersion(), newConfig.getConfigVersion()); version += 10'000 + SecureRandom().nextInt32(100'000); - newConfig.setConfigVersion(version); + auto newMutableConfig = newConfig.getMutable(); + newMutableConfig.setConfigVersion(version); + newConfig = ReplSetConfig(std::move(newMutableConfig)); } else { // Only append 'newlyAdded' to nodes during safe reconfig. if (enableAutomaticReconfig) { - bool addedNewlyAddedField = false; + boost::optional<MutableReplSetConfig> newMutableConfig; // Set the 'newlyAdded' field to true for all new voting nodes. for (int i = 0; i < newConfig.getNumMembers(); i++) { @@ -3285,12 +3289,15 @@ Status ReplicationCoordinatorImpl::processReplSetReconfig(OperationContext* opCt // 1) Is a new, voting node // 2) Already has a 'newlyAdded' field in the old config if (isNewVotingMember || isCurrentlyNewlyAdded) { - newConfig.addNewlyAddedFieldForMember(newMemId); - addedNewlyAddedField = true; + if (!newMutableConfig) { + newMutableConfig = newConfig.getMutable(); + } + newMutableConfig->addNewlyAddedFieldForMember(newMemId); } } - if (addedNewlyAddedField) { + if (newMutableConfig) { + newConfig = ReplSetConfig(*std::move(newMutableConfig)); LOGV2(4634400, "Appended the 'newlyAdded' field to a node in the new config. Nodes with " "the 'newlyAdded' field will be considered to have 'votes:0'. Upon " @@ -3572,7 +3579,7 @@ void ReplicationCoordinatorImpl::_finishReplSetReconfig(OperationContext* opCtx, newConfig.getWriteConcernMajorityShouldJournal(); // If the new config has the same content but different version and term, like on stepup, we // don't need to drop snapshots either, since the quorum condition is still the same. - auto newConfigCopy = newConfig; + auto newConfigCopy = newConfig.getMutable(); newConfigCopy.setConfigTerm(oldConfig.getConfigTerm()); newConfigCopy.setConfigVersion(oldConfig.getConfigVersion()); auto contentChanged = @@ -3692,7 +3699,7 @@ void ReplicationCoordinatorImpl::_reconfigToRemoveNewlyAddedField( << ", heartbeat data config version: " << versionAndTerm.toString()); } - auto newConfig = oldConfig; + auto newConfig = oldConfig.getMutable(); newConfig.setConfigVersion(newConfig.getConfigVersion() + 1); const auto hasNewlyAddedField = @@ -3702,7 +3709,7 @@ void ReplicationCoordinatorImpl::_reconfigToRemoveNewlyAddedField( } newConfig.removeNewlyAddedFieldForMember(memberId); - return newConfig; + return ReplSetConfig(std::move(newConfig)); }; auto opCtx = cc().makeOperationContext(); @@ -3760,8 +3767,10 @@ Status ReplicationCoordinatorImpl::processReplSetInitiate(OperationContext* opCt lk.unlock(); ReplSetConfig newConfig; - Status status = newConfig.initializeForInitiate(configObj, OID::gen()); - if (!status.isOK()) { + try { + newConfig = ReplSetConfig::parseForInitiate(configObj, OID::gen()); + } catch (const DBException& e) { + Status status = e.toStatus(); LOGV2_ERROR(21423, "replSet initiate got {error} while parsing {config}", "replSetInitiate error while parsing config", @@ -3800,7 +3809,7 @@ Status ReplicationCoordinatorImpl::processReplSetInitiate(OperationContext* opCt // In pv1, the TopologyCoordinator has not set the term yet. It will be set to kInitialTerm if // the initiate succeeds so we pass that here. - status = checkQuorumForInitiate( + auto status = checkQuorumForInitiate( _replExecutor.get(), newConfig, myIndex.getValue(), OpTime::kInitialTerm); if (!status.isOK()) { diff --git a/src/mongo/db/repl/replication_coordinator_impl_elect_v1_test.cpp b/src/mongo/db/repl/replication_coordinator_impl_elect_v1_test.cpp index 038c2568290..84fb48d6a7b 100644 --- a/src/mongo/db/repl/replication_coordinator_impl_elect_v1_test.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl_elect_v1_test.cpp @@ -558,17 +558,14 @@ TEST_F(ReplCoordTest, NodeWillNotStandForElectionDuringHeartbeatReconfig) { NetworkInterfaceMock* net = getNet(); net->enterNetwork(); ReplSetHeartbeatResponse hbResp2; - ReplSetConfig config; - config - .initialize(BSON("_id" - << "mySet" - << "version" << 3 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "node1:12345") - << BSON("_id" << 2 << "host" - << "node2:12345")) - << "protocolVersion" << 1)) - .transitional_ignore(); + auto config = ReplSetConfig::parse(BSON("_id" + << "mySet" + << "version" << 3 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "node1:12345") + << BSON("_id" << 2 << "host" + << "node2:12345")) + << "protocolVersion" << 1)); hbResp2.setConfig(config); hbResp2.setConfigVersion(3); hbResp2.setSetName("mySet"); diff --git a/src/mongo/db/repl/replication_coordinator_impl_heartbeat_v1_test.cpp b/src/mongo/db/repl/replication_coordinator_impl_heartbeat_v1_test.cpp index df5caa56f81..9160e037da7 100644 --- a/src/mongo/db/repl/replication_coordinator_impl_heartbeat_v1_test.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl_heartbeat_v1_test.cpp @@ -167,9 +167,8 @@ TEST_F(ReplCoordHBV1Test, assertMemberState(MemberState::RS_STARTUP2); OperationContextNoop opCtx; - ReplSetConfig storedConfig; - ASSERT_OK(storedConfig.initialize( - unittest::assertGet(getExternalState()->loadLocalConfigDocument(&opCtx)))); + auto storedConfig = ReplSetConfig::parse( + unittest::assertGet(getExternalState()->loadLocalConfigDocument(&opCtx))); ASSERT_OK(storedConfig.validate()); ASSERT_EQUALS(3, storedConfig.getConfigVersion()); ASSERT_EQUALS(3, storedConfig.getNumMembers()); @@ -635,9 +634,8 @@ TEST_F(ReplCoordHBV1Test, assertMemberState(MemberState::RS_ARBITER); OperationContextNoop opCtx; - ReplSetConfig storedConfig; - ASSERT_OK(storedConfig.initialize( - unittest::assertGet(getExternalState()->loadLocalConfigDocument(&opCtx)))); + auto storedConfig = ReplSetConfig::parse( + unittest::assertGet(getExternalState()->loadLocalConfigDocument(&opCtx))); ASSERT_OK(storedConfig.validate()); ASSERT_EQUALS(3, storedConfig.getConfigVersion()); ASSERT_EQUALS(3, storedConfig.getNumMembers()); @@ -1138,8 +1136,7 @@ void HBStepdownAndReconfigTest::sendHBResponse(int targetIndex, if (includeConfig) { auto configDoc = MutableDocument(Document(_initialConfig)); configDoc["version"] = Value(configVersion); - ReplSetConfig newConfig; - ASSERT_OK(newConfig.initialize(configDoc.freeze().toBson())); + auto newConfig = ReplSetConfig::parse(configDoc.freeze().toBson()); hbResp.setConfig(newConfig); } diff --git a/src/mongo/db/repl/replication_coordinator_impl_reconfig_test.cpp b/src/mongo/db/repl/replication_coordinator_impl_reconfig_test.cpp index 2c2919e830b..fd0c03f9d9a 100644 --- a/src/mongo/db/repl/replication_coordinator_impl_reconfig_test.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl_reconfig_test.cpp @@ -629,16 +629,13 @@ TEST_F( NetworkInterfaceMock* net = getNet(); net->enterNetwork(); ReplSetHeartbeatResponse hbResp2; - ReplSetConfig config; - config - .initialize(BSON("_id" - << "mySet" - << "version" << 3 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "node1:12345") - << BSON("_id" << 2 << "host" - << "node2:12345")))) - .transitional_ignore(); + auto config = ReplSetConfig::parse(BSON("_id" + << "mySet" + << "version" << 3 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "node1:12345") + << BSON("_id" << 2 << "host" + << "node2:12345")))); hbResp2.setConfig(config); hbResp2.setConfigVersion(3); hbResp2.setSetName("mySet"); @@ -697,16 +694,13 @@ TEST_F(ReplCoordTest, NodeDoesNotAcceptHeartbeatReconfigWhileInTheMidstOfReconfi net->runUntil(net->now() + Seconds(10)); // run until we've sent a heartbeat request const NetworkInterfaceMock::NetworkOperationIterator noi = net->getNextReadyRequest(); ReplSetHeartbeatResponse hbResp; - ReplSetConfig config; - config - .initialize(BSON("_id" - << "mySet" - << "version" << 4 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "node1:12345") - << BSON("_id" << 2 << "host" - << "node2:12345")))) - .transitional_ignore(); + auto config = ReplSetConfig::parse(BSON("_id" + << "mySet" + << "version" << 4 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "node1:12345") + << BSON("_id" << 2 << "host" + << "node2:12345")))); hbResp.setConfig(config); hbResp.setConfigVersion(4); hbResp.setSetName("mySet"); @@ -2114,7 +2108,7 @@ TEST_F(ReplCoordTest, StepUpReconfigConcurrentWithHeartbeatReconfig) { startCapturingLogMessages(); OpTime lastApplied(Timestamp(100, 1), 0); ReplSetHeartbeatResponse hbResp; - ASSERT_OK(rsConfig.initialize(newerConfig)); + rsConfig = ReplSetConfig::parse(newerConfig); hbResp.setConfig(rsConfig); hbResp.setSetName(rsConfig.getReplSetName()); hbResp.setState(MemberState::RS_SECONDARY); @@ -2193,7 +2187,7 @@ TEST_F(ReplCoordTest, StepUpReconfigConcurrentWithForceHeartbeatReconfig) { OpTime lastApplied(Timestamp(100, 1), 0); ReplSetHeartbeatResponse hbResp; - ASSERT_OK(rsConfig.initialize(newerConfig)); + rsConfig = ReplSetConfig::parse(newerConfig); hbResp.setConfig(rsConfig); hbResp.setSetName(rsConfig.getReplSetName()); hbResp.setState(MemberState::RS_SECONDARY); diff --git a/src/mongo/db/repl/replication_coordinator_impl_test.cpp b/src/mongo/db/repl/replication_coordinator_impl_test.cpp index 403dd3ab420..1334d289f44 100644 --- a/src/mongo/db/repl/replication_coordinator_impl_test.cpp +++ b/src/mongo/db/repl/replication_coordinator_impl_test.cpp @@ -4045,14 +4045,14 @@ TEST_F(ReplCoordTest, IsMasterOnRemovedNode) { // Receive a config that excludes node1 and with node2 having a configured horizon. ReplSetHeartbeatResponse hbResp; - ReplSetConfig removedFromConfig; - ASSERT_OK(removedFromConfig.initialize( - BSON("_id" - << "mySet" - << "protocolVersion" << 1 << "version" << 2 << "members" - << BSON_ARRAY(BSON("host" << nodeTwoHostName << "_id" << 2 << "horizons" - << BSON("horizon1" - << "testhorizon.com:100")))))); + auto removedFromConfig = + ReplSetConfig::parse(BSON("_id" + << "mySet" + << "protocolVersion" << 1 << "version" << 2 << "members" + << BSON_ARRAY(BSON("host" << nodeTwoHostName << "_id" << 2 + << "horizons" + << BSON("horizon1" + << "testhorizon.com:100"))))); hbResp.setConfig(removedFromConfig); hbResp.setConfigVersion(2); hbResp.setSetName("mySet"); @@ -4211,14 +4211,14 @@ TEST_F(ReplCoordTest, AwaitIsMasterRespondsCorrectlyWhenNodeRemovedAndReadded) { // Receive a config that excludes node1 and with node2 having a configured horizon. ReplSetHeartbeatResponse hbResp; - ReplSetConfig removedFromConfig; - ASSERT_OK(removedFromConfig.initialize( - BSON("_id" - << "mySet" - << "protocolVersion" << 1 << "version" << 2 << "members" - << BSON_ARRAY(BSON("host" << nodeTwoHostName << "_id" << 2 << "horizons" - << BSON("horizon1" - << "testhorizon.com:100")))))); + auto removedFromConfig = + ReplSetConfig::parse(BSON("_id" + << "mySet" + << "protocolVersion" << 1 << "version" << 2 << "members" + << BSON_ARRAY(BSON("host" << nodeTwoHostName << "_id" << 2 + << "horizons" + << BSON("horizon1" + << "testhorizon.com:100"))))); hbResp.setConfig(removedFromConfig); hbResp.setConfigVersion(2); hbResp.setSetName("mySet"); @@ -6664,15 +6664,12 @@ TEST_F(ReplCoordTest, // Respond to node1's heartbeat command with a config that excludes node1. ReplSetHeartbeatResponse hbResp; - ReplSetConfig config; - config - .initialize(BSON("_id" - << "mySet" - << "protocolVersion" << 1 << "version" << 3 << "members" - << BSON_ARRAY(BSON("host" - << "node2:12345" - << "_id" << 1)))) - .transitional_ignore(); + auto config = ReplSetConfig::parse(BSON("_id" + << "mySet" + << "protocolVersion" << 1 << "version" << 3 << "members" + << BSON_ARRAY(BSON("host" + << "node2:12345" + << "_id" << 1)))); hbResp.setConfig(config); hbResp.setConfigVersion(3); hbResp.setSetName("mySet"); diff --git a/src/mongo/db/repl/replication_coordinator_test_fixture.cpp b/src/mongo/db/repl/replication_coordinator_test_fixture.cpp index 792999c9674..78be2ece8b1 100644 --- a/src/mongo/db/repl/replication_coordinator_test_fixture.cpp +++ b/src/mongo/db/repl/replication_coordinator_test_fixture.cpp @@ -68,8 +68,7 @@ executor::TaskExecutor* ReplCoordTest::getReplExec() { } ReplSetConfig ReplCoordTest::assertMakeRSConfig(const BSONObj& configBson) { - ReplSetConfig config; - ASSERT_OK(config.initialize(configBson)); + auto config = ReplSetConfig::parse(configBson); ASSERT_OK(config.validate()); return config; } diff --git a/src/mongo/db/repl/topology_coordinator_v1_test.cpp b/src/mongo/db/repl/topology_coordinator_v1_test.cpp index 3ec624eb95f..fc370fbee11 100644 --- a/src/mongo/db/repl/topology_coordinator_v1_test.cpp +++ b/src/mongo/db/repl/topology_coordinator_v1_test.cpp @@ -201,8 +201,7 @@ protected: // Update config and set selfIndex // If "now" is passed in, set _now to now+1 void updateConfig(BSONObj cfg, int selfIndex, Date_t now = Date_t::fromMillisSinceEpoch(-1)) { - ReplSetConfig config; - ASSERT_OK(config.initialize(addProtocolVersion(cfg))); + auto config = ReplSetConfig::parse(addProtocolVersion(cfg)); ASSERT_OK(config.validate()); _selfIndex = selfIndex; @@ -2701,13 +2700,12 @@ TEST_F(TopoCoordTest, DoNotBecomeCandidateWhenReconfigToBeElectableInSingleNodeSetIfInMaintenanceMode) { ASSERT_TRUE(TopologyCoordinator::Role::kFollower == getTopoCoord().getRole()); ASSERT_EQUALS(MemberState::RS_STARTUP, getTopoCoord().getMemberState().s); - ReplSetConfig cfg; - ASSERT_OK(cfg.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "hself" - << "priority" << 0))))); + auto cfg = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "hself" + << "priority" << 0)))); getTopoCoord().updateConfig(cfg, 0, now()++); ASSERT_EQUALS(MemberState::RS_STARTUP2, getTopoCoord().getMemberState().s); @@ -2731,14 +2729,12 @@ TEST_F(TopoCoordTest, TEST_F(TopoCoordTest, NodeDoesNotBecomeCandidateWhenBecomingSecondaryInSingleNodeSetIfUnelectable) { ASSERT_TRUE(TopologyCoordinator::Role::kFollower == getTopoCoord().getRole()); ASSERT_EQUALS(MemberState::RS_STARTUP, getTopoCoord().getMemberState().s); - ReplSetConfig cfg; - cfg.initialize(BSON("_id" - << "rs0" - << "version" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 1 << "host" - << "hself" - << "priority" << 0)))) - .transitional_ignore(); + auto cfg = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "hself" + << "priority" << 0)))); getTopoCoord().updateConfig(cfg, 0, now()++); ASSERT_EQUALS(MemberState::RS_STARTUP2, getTopoCoord().getMemberState().s); @@ -4341,10 +4337,9 @@ public: }; TEST_F(HeartbeatResponseReconfigTestV1, NodeAcceptsConfigIfVersionInHeartbeatResponseIsNewer) { - ReplSetConfig config; long long version = initConfigVersion + 1; long long term = initConfigTerm; - config.initialize(makeRSConfigWithVersionAndTerm(version, term)).transitional_ignore(); + auto config = ReplSetConfig::parse(makeRSConfigWithVersionAndTerm(version, term)); ReplSetHeartbeatResponse hb; hb.initialize(BSON("ok" << 1 << "v" << 1 << "state" << MemberState::RS_SECONDARY), 1) @@ -4362,10 +4357,9 @@ TEST_F(HeartbeatResponseReconfigTestV1, NodeAcceptsConfigIfVersionInHeartbeatRes } TEST_F(HeartbeatResponseReconfigTestV1, NodeAcceptsConfigIfTermInHeartbeatResponseIsNewer) { - ReplSetConfig config; long long version = initConfigVersion; long long term = initConfigTerm + 1; - config.initialize(makeRSConfigWithVersionAndTerm(version, term)).transitional_ignore(); + auto config = ReplSetConfig::parse(makeRSConfigWithVersionAndTerm(version, term)); ReplSetHeartbeatResponse hb; hb.initialize(BSON("ok" << 1 << "v" << 1 << "state" << MemberState::RS_SECONDARY), 1) @@ -4384,10 +4378,9 @@ TEST_F(HeartbeatResponseReconfigTestV1, NodeAcceptsConfigIfTermInHeartbeatRespon TEST_F(HeartbeatResponseReconfigTestV1, NodeAcceptsConfigIfVersionInHeartbeatResponseIfNewerAndTermUninitialized) { - ReplSetConfig config; long long version = initConfigVersion + 1; long long term = OpTime::kUninitializedTerm; - config.initialize(makeRSConfigWithVersionAndTerm(version, term)).transitional_ignore(); + auto config = ReplSetConfig::parse(makeRSConfigWithVersionAndTerm(version, term)); ReplSetHeartbeatResponse hb; hb.initialize(BSON("ok" << 1 << "v" << 1 << "state" << MemberState::RS_SECONDARY), 1) @@ -4406,10 +4399,9 @@ TEST_F(HeartbeatResponseReconfigTestV1, TEST_F(HeartbeatResponseReconfigTestV1, NodeRejectsConfigInHeartbeatResponseIfVersionIsOlder) { // Older config version, same term. - ReplSetConfig config; long long version = (initConfigVersion - 1); long long term = initConfigTerm; - config.initialize(makeRSConfigWithVersionAndTerm(version, term)).transitional_ignore(); + auto config = ReplSetConfig::parse(makeRSConfigWithVersionAndTerm(version, term)); ReplSetHeartbeatResponse hb; hb.initialize(BSON("ok" << 1 << "v" << 1 << "state" << MemberState::RS_SECONDARY), 1) @@ -4428,10 +4420,9 @@ TEST_F(HeartbeatResponseReconfigTestV1, NodeRejectsConfigInHeartbeatResponseIfVe } TEST_F(HeartbeatResponseReconfigTestV1, NodeRejectsConfigInHeartbeatResponseIfConfigIsTheSame) { - ReplSetConfig config; long long version = initConfigVersion; long long term = initConfigTerm; - config.initialize(makeRSConfigWithVersionAndTerm(version, term)).transitional_ignore(); + auto config = ReplSetConfig::parse(makeRSConfigWithVersionAndTerm(version, term)); ReplSetHeartbeatResponse hb; hb.initialize(BSON("ok" << 1 << "v" << 1 << "state" << MemberState::RS_SECONDARY), 0) @@ -4451,10 +4442,9 @@ TEST_F(HeartbeatResponseReconfigTestV1, NodeRejectsConfigInHeartbeatResponseIfCo TEST_F(HeartbeatResponseReconfigTestV1, NodeRejectsConfigInHeartbeatResponseIfTermIsOlder) { // Older config term, same version - ReplSetConfig config; long long version = initConfigVersion; long long term = initConfigTerm - 1; - config.initialize(makeRSConfigWithVersionAndTerm(version, term)).transitional_ignore(); + auto config = ReplSetConfig::parse(makeRSConfigWithVersionAndTerm(version, term)); ReplSetHeartbeatResponse hb; hb.initialize(BSON("ok" << 1 << "v" << 1 << "state" << MemberState::RS_SECONDARY), 0) @@ -4475,10 +4465,9 @@ TEST_F(HeartbeatResponseReconfigTestV1, NodeRejectsConfigInHeartbeatResponseIfTe TEST_F(HeartbeatResponseReconfigTestV1, NodeRejectsConfigInHeartbeatResponseIfNewerVersionButOlderTerm) { // Newer version but older term. - ReplSetConfig config; long long version = (initConfigVersion + 1); long long term = (initConfigTerm - 1); - config.initialize(makeRSConfigWithVersionAndTerm(version, term)).transitional_ignore(); + auto config = ReplSetConfig::parse(makeRSConfigWithVersionAndTerm(version, term)); ReplSetHeartbeatResponse hb; hb.initialize(BSON("ok" << 1 << "v" << 1 << "state" << MemberState::RS_SECONDARY), 0) @@ -6004,8 +5993,7 @@ TEST_F(TopoCoordTest, ArbitersNotIncludedInW2WriteInPSSAAReplSet) { } TEST_F(TopoCoordTest, CheckIfCommitQuorumCanBeSatisfied) { - ReplSetConfig configA; - ASSERT_OK(configA.initialize(BSON( + auto configA = ReplSetConfig::parse(BSON( "_id" << "rs0" << "version" << 1 << "protocolVersion" << 1 << "members" @@ -6050,7 +6038,7 @@ TEST_F(TopoCoordTest, CheckIfCommitQuorumCanBeSatisfied) { << "settings" << BSON("getLastErrorModes" << BSON( "valid" << BSON("dc" << 2 << "rack" << 3) << "invalidNotEnoughValues" - << BSON("dc" << 3) << "invalidNotEnoughNodes" << BSON("rack" << 6)))))); + << BSON("dc" << 3) << "invalidNotEnoughNodes" << BSON("rack" << 6))))); getTopoCoord().updateConfig(configA, -1, Date_t()); CommitQuorumOptions validNumberCQ; @@ -7094,20 +7082,17 @@ TEST_F(HeartbeatResponseHighVerbosityTestV1, UpdateHeartbeatDataSameConfig) { // construct a copy of the original config for log message checking later // see HeartbeatResponseTest for the origin of the original config - ReplSetConfig originalConfig; - originalConfig - .initialize(BSON("_id" - << "rs0" - << "version" << 5 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "host1:27017") - << BSON("_id" << 1 << "host" - << "host2:27017") - << BSON("_id" << 2 << "host" - << "host3:27017")) - << "protocolVersion" << 1 << "settings" - << BSON("heartbeatTimeoutSecs" << 5))) - .transitional_ignore(); + auto originalConfig = ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 5 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "host1:27017") + << BSON("_id" << 1 << "host" + << "host2:27017") + << BSON("_id" << 2 << "host" + << "host3:27017")) + << "protocolVersion" << 1 << "settings" + << BSON("heartbeatTimeoutSecs" << 5))); ReplSetHeartbeatResponse sameConfigResponse; sameConfigResponse.setSetName("rs0"); diff --git a/src/mongo/db/repl/vote_requester_test.cpp b/src/mongo/db/repl/vote_requester_test.cpp index 8fc176e0c10..463d532759d 100644 --- a/src/mongo/db/repl/vote_requester_test.cpp +++ b/src/mongo/db/repl/vote_requester_test.cpp @@ -88,24 +88,23 @@ TEST(ReplSetRequestVotes, ResponseAcceptsUnknownField) { class VoteRequesterTest : public mongo::unittest::Test { public: virtual void setUp() { - ReplSetConfig config; - ASSERT_OK( - config.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "host0") - << BSON("_id" << 1 << "host" - << "host1") - << BSON("_id" << 2 << "host" - << "host2") - << BSON("_id" << 3 << "host" - << "host3" - << "votes" << 0 << "priority" << 0) - << BSON("_id" << 4 << "host" - << "host4" - << "votes" << 0 << "priority" - << 0))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY( + BSON("_id" << 0 << "host" + << "host0") + << BSON("_id" << 1 << "host" + << "host1") + << BSON("_id" << 2 << "host" + << "host2") + << BSON("_id" << 3 << "host" + << "host3" + << "votes" << 0 << "priority" << 0) + << BSON("_id" << 4 << "host" + << "host4" + << "votes" << 0 << "priority" << 0))))); ASSERT_OK(config.validate()); long long candidateId = 0; long long term = 2; @@ -237,24 +236,23 @@ protected: class VoteRequesterDryRunTest : public VoteRequesterTest { public: virtual void setUp() { - ReplSetConfig config; - ASSERT_OK( - config.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "host0") - << BSON("_id" << 1 << "host" - << "host1") - << BSON("_id" << 2 << "host" - << "host2") - << BSON("_id" << 3 << "host" - << "host3" - << "votes" << 0 << "priority" << 0) - << BSON("_id" << 4 << "host" - << "host4" - << "votes" << 0 << "priority" - << 0))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY( + BSON("_id" << 0 << "host" + << "host0") + << BSON("_id" << 1 << "host" + << "host1") + << BSON("_id" << 2 << "host" + << "host2") + << BSON("_id" << 3 << "host" + << "host3" + << "votes" << 0 << "priority" << 0) + << BSON("_id" << 4 << "host" + << "host4" + << "votes" << 0 << "priority" << 0))))); ASSERT_OK(config.validate()); long long candidateId = 0; long long term = 2; @@ -272,20 +270,20 @@ public: class VoteRequesterCatchupTakeoverDryRunTest : public VoteRequesterTest { public: virtual void setUp() { - ReplSetConfig config; - ASSERT_OK(config.initialize(BSON("_id" - << "rs0" - << "version" << 2 << "protocolVersion" << 1 << "members" - << BSON_ARRAY(BSON("_id" << 0 << "host" - << "host0") - << BSON("_id" << 1 << "host" - << "host1") - << BSON("_id" << 2 << "host" - << "host2") - << BSON("_id" << 3 << "host" - << "host3") - << BSON("_id" << 4 << "host" - << "host4"))))); + ReplSetConfig config( + ReplSetConfig::parse(BSON("_id" + << "rs0" + << "version" << 2 << "protocolVersion" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "host0") + << BSON("_id" << 1 << "host" + << "host1") + << BSON("_id" << 2 << "host" + << "host2") + << BSON("_id" << 3 << "host" + << "host3") + << BSON("_id" << 4 << "host" + << "host4"))))); ASSERT_OK(config.validate()); long long candidateId = 0; long long term = 2; diff --git a/src/mongo/dbtests/mock/mock_replica_set.cpp b/src/mongo/dbtests/mock/mock_replica_set.cpp index 12e288ab1a7..d7dfb75aec1 100644 --- a/src/mongo/dbtests/mock/mock_replica_set.cpp +++ b/src/mongo/dbtests/mock/mock_replica_set.cpp @@ -80,7 +80,11 @@ MockReplicaSet::MockReplicaSet(const string& setName, membersBuilder.done(); ReplSetConfig replConfig; - fassert(28566, replConfig.initialize(configBuilder.obj())); + try { + replConfig = ReplSetConfig::parse(configBuilder.obj()); + } catch (const DBException&) { + fassertFailed(28566); + } fassert(28573, replConfig.validate()); setConfig(replConfig); } diff --git a/src/mongo/dbtests/mock_replica_set_test.cpp b/src/mongo/dbtests/mock_replica_set_test.cpp index 398c6dfd85d..e3461193747 100644 --- a/src/mongo/dbtests/mock_replica_set_test.cpp +++ b/src/mongo/dbtests/mock_replica_set_test.cpp @@ -284,8 +284,7 @@ ReplSetConfig _getConfigWithMemberRemoved(const ReplSetConfig& oldConfig, } membersBuilder.done(); - ReplSetConfig newConfig; - ASSERT_OK(newConfig.initialize(newConfigBuilder.obj())); + ReplSetConfig newConfig(ReplSetConfig::parse(newConfigBuilder.obj())); ASSERT_OK(newConfig.validate()); return newConfig; } diff --git a/src/mongo/dbtests/scanning_replica_set_monitor_test.cpp b/src/mongo/dbtests/scanning_replica_set_monitor_test.cpp index 0afc810c438..3567e9a0922 100644 --- a/src/mongo/dbtests/scanning_replica_set_monitor_test.cpp +++ b/src/mongo/dbtests/scanning_replica_set_monitor_test.cpp @@ -128,8 +128,7 @@ repl::ReplSetConfig _getConfigWithMemberRemoved(const repl::ReplSetConfig& oldCo } membersBuilder.done(); - repl::ReplSetConfig newConfig; - ASSERT_OK(newConfig.initialize(newConfigBuilder.obj())); + auto newConfig = repl::ReplSetConfig::parse(newConfigBuilder.obj()); ASSERT_OK(newConfig.validate()); return newConfig; } diff --git a/src/mongo/s/sharding_mongod_test_fixture.cpp b/src/mongo/s/sharding_mongod_test_fixture.cpp index 6572711d093..b051dece981 100644 --- a/src/mongo/s/sharding_mongod_test_fixture.cpp +++ b/src/mongo/s/sharding_mongod_test_fixture.cpp @@ -115,9 +115,9 @@ void ShardingMongodTestFixture::setUp() { for (size_t i = 0; i < _servers.size(); ++i) { serversBob.append(BSON("host" << _servers[i].toString() << "_id" << static_cast<int>(i))); } - repl::ReplSetConfig replSetConfig; - ASSERT_OK(replSetConfig.initialize(BSON("_id" << _setName << "protocolVersion" << 1 << "version" - << 3 << "members" << serversBob.arr()))); + auto replSetConfig = + repl::ReplSetConfig::parse(BSON("_id" << _setName << "protocolVersion" << 1 << "version" + << 3 << "members" << serversBob.arr())); replCoordPtr->setGetConfigReturnValue(replSetConfig); repl::ReplicationCoordinator::set(service, std::move(replCoordPtr)); |