Skip to content
This repository was archived by the owner on Oct 31, 2023. It is now read-only.

Commit 9c5d82f

Browse files
will62794Evergreen Agent
authored andcommitted
SERVER-46720 Allow non strict replication message parsing
1 parent 90e5668 commit 9c5d82f

8 files changed

+111
-36
lines changed

src/mongo/db/repl/repl_set_heartbeat_args_v1.cpp

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,25 +49,11 @@ const std::string kSenderHostFieldName = "from";
4949
const std::string kSenderIdFieldName = "fromId";
5050
const std::string kSetNameFieldName = "replSetHeartbeat";
5151
const std::string kTermFieldName = "term";
52-
53-
const std::string kLegalHeartbeatFieldNames[] = {kCheckEmptyFieldName,
54-
kConfigVersionFieldName,
55-
kConfigTermFieldName,
56-
kHeartbeatVersionFieldName,
57-
kSenderHostFieldName,
58-
kSenderIdFieldName,
59-
kSetNameFieldName,
60-
kTermFieldName};
61-
6252
} // namespace
6353

6454
Status ReplSetHeartbeatArgsV1::initialize(const BSONObj& argsObj) {
65-
Status status = bsonCheckOnlyHasFieldsForCommand(
66-
"ReplSetHeartbeatArgs", argsObj, kLegalHeartbeatFieldNames);
67-
if (!status.isOK())
68-
return status;
69-
70-
status = bsonExtractBooleanFieldWithDefault(argsObj, kCheckEmptyFieldName, false, &_checkEmpty);
55+
Status status =
56+
bsonExtractBooleanFieldWithDefault(argsObj, kCheckEmptyFieldName, false, &_checkEmpty);
7157
if (!status.isOK())
7258
return status;
7359

src/mongo/db/repl/repl_set_heartbeat_response_test.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,13 @@ TEST(ReplSetHeartbeatResponse, DefaultConstructThenSlowlyBuildToFullObj) {
124124
ASSERT_EQUALS(2, hbResponseObj["state"].numberLong());
125125
ASSERT_EQUALS("syncTarget:27017", hbResponseObj["syncingTo"].String());
126126

127-
initializeResult = hbResponseObjRoundTripChecker.initialize(hbResponseObj, 0);
127+
// Verify that we allow an unknown field.
128+
BSONObjBuilder hbResponseBob;
129+
hbResponseBob.appendElements(hbResponseObj);
130+
hbResponseBob.append("unknownField", 1);
131+
auto cmdObj = hbResponseBob.obj();
132+
133+
initializeResult = hbResponseObjRoundTripChecker.initialize(cmdObj, 0);
128134
ASSERT_EQUALS(Status::OK(), initializeResult);
129135
ASSERT_EQUALS(hbResponseObj.toString(), hbResponseObjRoundTripChecker.toBSON().toString());
130136
}

src/mongo/db/repl/repl_set_request_votes_args.cpp

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -51,27 +51,11 @@ const std::string kSetNameFieldName = "setName";
5151
const std::string kTermFieldName = "term";
5252
const std::string kVoteGrantedFieldName = "voteGranted";
5353
const std::string kOperationTime = "operationTime";
54-
55-
const std::string kLegalArgsFieldNames[] = {
56-
kCandidateIndexFieldName,
57-
kCommandName,
58-
kConfigVersionFieldName,
59-
kConfigTermFieldName,
60-
kDryRunFieldName,
61-
kLastAppliedOpTimeFieldName,
62-
kSetNameFieldName,
63-
kTermFieldName,
64-
kOperationTime,
65-
};
66-
6754
} // namespace
6855

6956

7057
Status ReplSetRequestVotesArgs::initialize(const BSONObj& argsObj) {
71-
Status status =
72-
bsonCheckOnlyHasFieldsForCommand("ReplSetRequestVotes", argsObj, kLegalArgsFieldNames);
73-
74-
status = bsonExtractIntegerField(argsObj, kTermFieldName, &_term);
58+
Status status = bsonExtractIntegerField(argsObj, kTermFieldName, &_term);
7559
if (!status.isOK())
7660
return status;
7761

src/mongo/db/repl/replication_coordinator_impl_heartbeat_v1_test.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,27 @@ using executor::NetworkInterfaceMock;
5656
using executor::RemoteCommandRequest;
5757
using executor::RemoteCommandResponse;
5858

59+
TEST(ReplSetHeartbeatArgs, AcceptsUnknownField) {
60+
ReplSetHeartbeatArgsV1 hbArgs;
61+
hbArgs.setConfigTerm(1);
62+
hbArgs.setConfigVersion(1);
63+
hbArgs.setHeartbeatVersion(1);
64+
hbArgs.setTerm(1);
65+
hbArgs.setSenderHost(HostAndPort("host:1"));
66+
hbArgs.setSetName("replSet");
67+
BSONObjBuilder bob;
68+
hbArgs.addToBSON(&bob);
69+
bob.append("unknownField", 1); // append an unknown field.
70+
BSONObj cmdObj = bob.obj();
71+
ASSERT_OK(hbArgs.initialize(cmdObj));
72+
73+
// The serialized object should be the same as the original except for the unknown field.
74+
BSONObjBuilder bob2;
75+
hbArgs.addToBSON(&bob2);
76+
bob2.append("unknownField", 1);
77+
ASSERT_BSONOBJ_EQ(bob2.obj(), cmdObj);
78+
}
79+
5980
class ReplCoordHBV1Test : public ReplCoordTest {
6081
protected:
6182
void assertMemberState(MemberState expected, std::string msg = "");

src/mongo/db/repl/reporter_test.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,44 @@ void ReporterTest::assertReporterDone() {
234234
ASSERT_EQUALS(reporter->join(), reporter->trigger());
235235
}
236236

237+
TEST(UpdatePositionArgs, AcceptsUnknownField) {
238+
UpdatePositionArgs updatePositionArgs;
239+
BSONObjBuilder bob;
240+
bob.append(UpdatePositionArgs::kCommandFieldName, 1);
241+
bob.append(UpdatePositionArgs::kUpdateArrayFieldName, BSONArray());
242+
bob.append("unknownField", 1); // append an unknown field.
243+
BSONObj cmdObj = bob.obj();
244+
ASSERT_OK(updatePositionArgs.initialize(cmdObj));
245+
}
246+
TEST(UpdatePositionArgs, AcceptsUnknownFieldInUpdateInfo) {
247+
UpdatePositionArgs updatePositionArgs;
248+
BSONObjBuilder bob;
249+
bob.append(UpdatePositionArgs::kCommandFieldName, 1);
250+
auto now = Date_t();
251+
auto updateInfo =
252+
BSON(UpdatePositionArgs::kConfigVersionFieldName
253+
<< 1 << UpdatePositionArgs::kMemberIdFieldName << 1
254+
<< UpdatePositionArgs::kDurableOpTimeFieldName << OpTime()
255+
<< UpdatePositionArgs::kAppliedOpTimeFieldName << OpTime()
256+
<< UpdatePositionArgs::kAppliedWallTimeFieldName << now
257+
<< UpdatePositionArgs::kDurableWallTimeFieldName << now << "unknownField" << 1);
258+
bob.append(UpdatePositionArgs::kUpdateArrayFieldName, BSON_ARRAY(updateInfo));
259+
BSONObj cmdObj = bob.obj();
260+
ASSERT_OK(updatePositionArgs.initialize(cmdObj));
261+
262+
// The serialized object should be the same as the original except for the unknown field.
263+
BSONObjBuilder bob2;
264+
auto updateArgsObj = updatePositionArgs.toBSON();
265+
auto updatesArr =
266+
BSONArray(updateArgsObj.getObjectField(UpdatePositionArgs::kUpdateArrayFieldName));
267+
ASSERT_EQ(updatesArr.nFields(), 1);
268+
bob2.appendElements(updatesArr[0].Obj());
269+
bob2.append(UpdatePositionArgs::kAppliedWallTimeFieldName, now);
270+
bob2.append(UpdatePositionArgs::kDurableWallTimeFieldName, now);
271+
bob2.append("unknownField", 1);
272+
ASSERT_EQ(bob2.obj().woCompare(updateInfo), 0);
273+
}
274+
237275
TEST_F(ReporterTestNoTriggerAtSetUp, InvalidConstruction) {
238276
// null PrepareReplSetUpdatePositionCommandFn
239277
ASSERT_THROWS(Reporter(&getExecutor(),

src/mongo/db/repl/vote_requester_test.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,36 @@ bool stringContains(const std::string& haystack, const std::string& needle) {
5454
return haystack.find(needle) != std::string::npos;
5555
}
5656

57+
TEST(ReplSetRequestVotes, ArgsAcceptsUnknownField) {
58+
ReplSetRequestVotesArgs requestVoteArgs;
59+
BSONObjBuilder bob;
60+
requestVoteArgs.addToBSON(&bob);
61+
bob.append("unknownField", 1); // append an unknown field.
62+
BSONObj cmdObj = bob.obj();
63+
ASSERT_OK(requestVoteArgs.initialize(cmdObj));
64+
65+
// The serialized object should be the same as the original except for the unknown field.
66+
BSONObjBuilder bob2;
67+
requestVoteArgs.addToBSON(&bob2);
68+
bob2.append("unknownField", 1);
69+
ASSERT_BSONOBJ_EQ(bob2.obj(), cmdObj);
70+
}
71+
72+
TEST(ReplSetRequestVotes, ResponseAcceptsUnknownField) {
73+
ReplSetRequestVotesResponse requestVoteRes;
74+
BSONObjBuilder bob;
75+
requestVoteRes.addToBSON(&bob);
76+
bob.append("unknownField", 1); // append an unknown field.
77+
BSONObj cmdObj = bob.obj();
78+
ASSERT_OK(requestVoteRes.initialize(cmdObj));
79+
80+
// The serialized object should be the same as the original except for the unknown field.
81+
BSONObjBuilder bob2;
82+
requestVoteRes.addToBSON(&bob2);
83+
bob2.append("unknownField", 1);
84+
ASSERT_BSONOBJ_EQ(bob2.obj(), cmdObj);
85+
}
86+
5787

5888
class VoteRequesterTest : public mongo::unittest::Test {
5989
public:

src/mongo/rpc/metadata/oplog_query_metadata_test.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,12 @@ TEST(ReplResponseMetadataTest, OplogQueryMetadataRoundtrip) {
6262
BSONObj serializedObj = builder.obj();
6363
ASSERT_BSONOBJ_EQ(expectedObj, serializedObj);
6464

65-
auto cloneStatus = OplogQueryMetadata::readFromMetadata(serializedObj);
65+
// Verify that we allow unknown fields.
66+
BSONObjBuilder bob;
67+
bob.appendElements(serializedObj);
68+
bob.append("unknownField", 1);
69+
70+
auto cloneStatus = OplogQueryMetadata::readFromMetadata(bob.obj());
6671
ASSERT_OK(cloneStatus.getStatus());
6772

6873
const auto& clonedMetadata = cloneStatus.getValue();

src/mongo/rpc/metadata/repl_set_metadata_test.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,12 @@ TEST(ReplResponseMetadataTest, Roundtrip) {
7373
BSONObj serializedObj = builder.obj();
7474
ASSERT_BSONOBJ_EQ(expectedObj, serializedObj);
7575

76-
auto cloneStatus = ReplSetMetadata::readFromMetadata(serializedObj);
76+
// Verify that we allow unknown fields.
77+
BSONObjBuilder bob;
78+
bob.appendElements(serializedObj);
79+
bob.append("unknownField", 1);
80+
81+
auto cloneStatus = ReplSetMetadata::readFromMetadata(bob.obj());
7782
ASSERT_OK(cloneStatus.getStatus());
7883

7984
const auto& clonedMetadata = cloneStatus.getValue();

0 commit comments

Comments
 (0)