diff options
author | William Schultz <william.schultz@mongodb.com> | 2020-04-09 20:09:25 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-04-10 00:34:43 +0000 |
commit | 9c5d82ff1fb2bb7367e10c9e21ac67b440e7097e (patch) | |
tree | b0149e2037ba2bfddb0ad40b617336e1253f8a3b /src | |
parent | 90e56683e8d9c24f155ffbb64bb13b4169c924e8 (diff) | |
download | mongo-9c5d82ff1fb2bb7367e10c9e21ac67b440e7097e.tar.gz |
SERVER-46720 Allow non strict replication message parsing
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/repl/repl_set_heartbeat_args_v1.cpp | 18 | ||||
-rw-r--r-- | src/mongo/db/repl/repl_set_heartbeat_response_test.cpp | 8 | ||||
-rw-r--r-- | src/mongo/db/repl/repl_set_request_votes_args.cpp | 18 | ||||
-rw-r--r-- | src/mongo/db/repl/replication_coordinator_impl_heartbeat_v1_test.cpp | 21 | ||||
-rw-r--r-- | src/mongo/db/repl/reporter_test.cpp | 38 | ||||
-rw-r--r-- | src/mongo/db/repl/vote_requester_test.cpp | 30 | ||||
-rw-r--r-- | src/mongo/rpc/metadata/oplog_query_metadata_test.cpp | 7 | ||||
-rw-r--r-- | src/mongo/rpc/metadata/repl_set_metadata_test.cpp | 7 |
8 files changed, 111 insertions, 36 deletions
diff --git a/src/mongo/db/repl/repl_set_heartbeat_args_v1.cpp b/src/mongo/db/repl/repl_set_heartbeat_args_v1.cpp index d97b1d15759..688e99b1250 100644 --- a/src/mongo/db/repl/repl_set_heartbeat_args_v1.cpp +++ b/src/mongo/db/repl/repl_set_heartbeat_args_v1.cpp @@ -49,25 +49,11 @@ const std::string kSenderHostFieldName = "from"; const std::string kSenderIdFieldName = "fromId"; const std::string kSetNameFieldName = "replSetHeartbeat"; const std::string kTermFieldName = "term"; - -const std::string kLegalHeartbeatFieldNames[] = {kCheckEmptyFieldName, - kConfigVersionFieldName, - kConfigTermFieldName, - kHeartbeatVersionFieldName, - kSenderHostFieldName, - kSenderIdFieldName, - kSetNameFieldName, - kTermFieldName}; - } // namespace Status ReplSetHeartbeatArgsV1::initialize(const BSONObj& argsObj) { - Status status = bsonCheckOnlyHasFieldsForCommand( - "ReplSetHeartbeatArgs", argsObj, kLegalHeartbeatFieldNames); - if (!status.isOK()) - return status; - - status = bsonExtractBooleanFieldWithDefault(argsObj, kCheckEmptyFieldName, false, &_checkEmpty); + Status status = + bsonExtractBooleanFieldWithDefault(argsObj, kCheckEmptyFieldName, false, &_checkEmpty); if (!status.isOK()) return status; diff --git a/src/mongo/db/repl/repl_set_heartbeat_response_test.cpp b/src/mongo/db/repl/repl_set_heartbeat_response_test.cpp index 3851ebda892..07c1966fdd5 100644 --- a/src/mongo/db/repl/repl_set_heartbeat_response_test.cpp +++ b/src/mongo/db/repl/repl_set_heartbeat_response_test.cpp @@ -124,7 +124,13 @@ TEST(ReplSetHeartbeatResponse, DefaultConstructThenSlowlyBuildToFullObj) { ASSERT_EQUALS(2, hbResponseObj["state"].numberLong()); ASSERT_EQUALS("syncTarget:27017", hbResponseObj["syncingTo"].String()); - initializeResult = hbResponseObjRoundTripChecker.initialize(hbResponseObj, 0); + // Verify that we allow an unknown field. + BSONObjBuilder hbResponseBob; + hbResponseBob.appendElements(hbResponseObj); + hbResponseBob.append("unknownField", 1); + auto cmdObj = hbResponseBob.obj(); + + initializeResult = hbResponseObjRoundTripChecker.initialize(cmdObj, 0); ASSERT_EQUALS(Status::OK(), initializeResult); ASSERT_EQUALS(hbResponseObj.toString(), hbResponseObjRoundTripChecker.toBSON().toString()); } diff --git a/src/mongo/db/repl/repl_set_request_votes_args.cpp b/src/mongo/db/repl/repl_set_request_votes_args.cpp index b685bb0ab4e..7978b26987f 100644 --- a/src/mongo/db/repl/repl_set_request_votes_args.cpp +++ b/src/mongo/db/repl/repl_set_request_votes_args.cpp @@ -51,27 +51,11 @@ const std::string kSetNameFieldName = "setName"; const std::string kTermFieldName = "term"; const std::string kVoteGrantedFieldName = "voteGranted"; const std::string kOperationTime = "operationTime"; - -const std::string kLegalArgsFieldNames[] = { - kCandidateIndexFieldName, - kCommandName, - kConfigVersionFieldName, - kConfigTermFieldName, - kDryRunFieldName, - kLastAppliedOpTimeFieldName, - kSetNameFieldName, - kTermFieldName, - kOperationTime, -}; - } // namespace Status ReplSetRequestVotesArgs::initialize(const BSONObj& argsObj) { - Status status = - bsonCheckOnlyHasFieldsForCommand("ReplSetRequestVotes", argsObj, kLegalArgsFieldNames); - - status = bsonExtractIntegerField(argsObj, kTermFieldName, &_term); + Status status = bsonExtractIntegerField(argsObj, kTermFieldName, &_term); if (!status.isOK()) return status; 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 ed453a28f1f..4a1a347b0d2 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 @@ -56,6 +56,27 @@ using executor::NetworkInterfaceMock; using executor::RemoteCommandRequest; using executor::RemoteCommandResponse; +TEST(ReplSetHeartbeatArgs, AcceptsUnknownField) { + ReplSetHeartbeatArgsV1 hbArgs; + hbArgs.setConfigTerm(1); + hbArgs.setConfigVersion(1); + hbArgs.setHeartbeatVersion(1); + hbArgs.setTerm(1); + hbArgs.setSenderHost(HostAndPort("host:1")); + hbArgs.setSetName("replSet"); + BSONObjBuilder bob; + hbArgs.addToBSON(&bob); + bob.append("unknownField", 1); // append an unknown field. + BSONObj cmdObj = bob.obj(); + ASSERT_OK(hbArgs.initialize(cmdObj)); + + // The serialized object should be the same as the original except for the unknown field. + BSONObjBuilder bob2; + hbArgs.addToBSON(&bob2); + bob2.append("unknownField", 1); + ASSERT_BSONOBJ_EQ(bob2.obj(), cmdObj); +} + class ReplCoordHBV1Test : public ReplCoordTest { protected: void assertMemberState(MemberState expected, std::string msg = ""); diff --git a/src/mongo/db/repl/reporter_test.cpp b/src/mongo/db/repl/reporter_test.cpp index f4538c6c6fa..260c50bbbfc 100644 --- a/src/mongo/db/repl/reporter_test.cpp +++ b/src/mongo/db/repl/reporter_test.cpp @@ -234,6 +234,44 @@ void ReporterTest::assertReporterDone() { ASSERT_EQUALS(reporter->join(), reporter->trigger()); } +TEST(UpdatePositionArgs, AcceptsUnknownField) { + UpdatePositionArgs updatePositionArgs; + BSONObjBuilder bob; + bob.append(UpdatePositionArgs::kCommandFieldName, 1); + bob.append(UpdatePositionArgs::kUpdateArrayFieldName, BSONArray()); + bob.append("unknownField", 1); // append an unknown field. + BSONObj cmdObj = bob.obj(); + ASSERT_OK(updatePositionArgs.initialize(cmdObj)); +} +TEST(UpdatePositionArgs, AcceptsUnknownFieldInUpdateInfo) { + UpdatePositionArgs updatePositionArgs; + BSONObjBuilder bob; + bob.append(UpdatePositionArgs::kCommandFieldName, 1); + auto now = Date_t(); + auto updateInfo = + BSON(UpdatePositionArgs::kConfigVersionFieldName + << 1 << UpdatePositionArgs::kMemberIdFieldName << 1 + << UpdatePositionArgs::kDurableOpTimeFieldName << OpTime() + << UpdatePositionArgs::kAppliedOpTimeFieldName << OpTime() + << UpdatePositionArgs::kAppliedWallTimeFieldName << now + << UpdatePositionArgs::kDurableWallTimeFieldName << now << "unknownField" << 1); + bob.append(UpdatePositionArgs::kUpdateArrayFieldName, BSON_ARRAY(updateInfo)); + BSONObj cmdObj = bob.obj(); + ASSERT_OK(updatePositionArgs.initialize(cmdObj)); + + // The serialized object should be the same as the original except for the unknown field. + BSONObjBuilder bob2; + auto updateArgsObj = updatePositionArgs.toBSON(); + auto updatesArr = + BSONArray(updateArgsObj.getObjectField(UpdatePositionArgs::kUpdateArrayFieldName)); + ASSERT_EQ(updatesArr.nFields(), 1); + bob2.appendElements(updatesArr[0].Obj()); + bob2.append(UpdatePositionArgs::kAppliedWallTimeFieldName, now); + bob2.append(UpdatePositionArgs::kDurableWallTimeFieldName, now); + bob2.append("unknownField", 1); + ASSERT_EQ(bob2.obj().woCompare(updateInfo), 0); +} + TEST_F(ReporterTestNoTriggerAtSetUp, InvalidConstruction) { // null PrepareReplSetUpdatePositionCommandFn ASSERT_THROWS(Reporter(&getExecutor(), diff --git a/src/mongo/db/repl/vote_requester_test.cpp b/src/mongo/db/repl/vote_requester_test.cpp index b5155003603..8fc176e0c10 100644 --- a/src/mongo/db/repl/vote_requester_test.cpp +++ b/src/mongo/db/repl/vote_requester_test.cpp @@ -54,6 +54,36 @@ bool stringContains(const std::string& haystack, const std::string& needle) { return haystack.find(needle) != std::string::npos; } +TEST(ReplSetRequestVotes, ArgsAcceptsUnknownField) { + ReplSetRequestVotesArgs requestVoteArgs; + BSONObjBuilder bob; + requestVoteArgs.addToBSON(&bob); + bob.append("unknownField", 1); // append an unknown field. + BSONObj cmdObj = bob.obj(); + ASSERT_OK(requestVoteArgs.initialize(cmdObj)); + + // The serialized object should be the same as the original except for the unknown field. + BSONObjBuilder bob2; + requestVoteArgs.addToBSON(&bob2); + bob2.append("unknownField", 1); + ASSERT_BSONOBJ_EQ(bob2.obj(), cmdObj); +} + +TEST(ReplSetRequestVotes, ResponseAcceptsUnknownField) { + ReplSetRequestVotesResponse requestVoteRes; + BSONObjBuilder bob; + requestVoteRes.addToBSON(&bob); + bob.append("unknownField", 1); // append an unknown field. + BSONObj cmdObj = bob.obj(); + ASSERT_OK(requestVoteRes.initialize(cmdObj)); + + // The serialized object should be the same as the original except for the unknown field. + BSONObjBuilder bob2; + requestVoteRes.addToBSON(&bob2); + bob2.append("unknownField", 1); + ASSERT_BSONOBJ_EQ(bob2.obj(), cmdObj); +} + class VoteRequesterTest : public mongo::unittest::Test { public: diff --git a/src/mongo/rpc/metadata/oplog_query_metadata_test.cpp b/src/mongo/rpc/metadata/oplog_query_metadata_test.cpp index 8fc74167115..bb267ccac59 100644 --- a/src/mongo/rpc/metadata/oplog_query_metadata_test.cpp +++ b/src/mongo/rpc/metadata/oplog_query_metadata_test.cpp @@ -62,7 +62,12 @@ TEST(ReplResponseMetadataTest, OplogQueryMetadataRoundtrip) { BSONObj serializedObj = builder.obj(); ASSERT_BSONOBJ_EQ(expectedObj, serializedObj); - auto cloneStatus = OplogQueryMetadata::readFromMetadata(serializedObj); + // Verify that we allow unknown fields. + BSONObjBuilder bob; + bob.appendElements(serializedObj); + bob.append("unknownField", 1); + + auto cloneStatus = OplogQueryMetadata::readFromMetadata(bob.obj()); ASSERT_OK(cloneStatus.getStatus()); const auto& clonedMetadata = cloneStatus.getValue(); diff --git a/src/mongo/rpc/metadata/repl_set_metadata_test.cpp b/src/mongo/rpc/metadata/repl_set_metadata_test.cpp index 9a121fd20d5..b7c1b0825a3 100644 --- a/src/mongo/rpc/metadata/repl_set_metadata_test.cpp +++ b/src/mongo/rpc/metadata/repl_set_metadata_test.cpp @@ -73,7 +73,12 @@ TEST(ReplResponseMetadataTest, Roundtrip) { BSONObj serializedObj = builder.obj(); ASSERT_BSONOBJ_EQ(expectedObj, serializedObj); - auto cloneStatus = ReplSetMetadata::readFromMetadata(serializedObj); + // Verify that we allow unknown fields. + BSONObjBuilder bob; + bob.appendElements(serializedObj); + bob.append("unknownField", 1); + + auto cloneStatus = ReplSetMetadata::readFromMetadata(bob.obj()); ASSERT_OK(cloneStatus.getStatus()); const auto& clonedMetadata = cloneStatus.getValue(); |