diff options
Diffstat (limited to 'src/mongo/db/repl/vote_requester_test.cpp')
-rw-r--r-- | src/mongo/db/repl/vote_requester_test.cpp | 623 |
1 files changed, 313 insertions, 310 deletions
diff --git a/src/mongo/db/repl/vote_requester_test.cpp b/src/mongo/db/repl/vote_requester_test.cpp index d5b9d9ce3d5..fb5fb8d757f 100644 --- a/src/mongo/db/repl/vote_requester_test.cpp +++ b/src/mongo/db/repl/vote_requester_test.cpp @@ -44,345 +44,348 @@ namespace mongo { namespace repl { namespace { - using executor::NetworkInterfaceMock; - using unittest::assertGet; - - using RemoteCommandRequest = RemoteCommandRequest; - - bool stringContains(const std::string &haystack, const std::string& needle) { - return haystack.find(needle) != std::string::npos; - } - - - class VoteRequesterTest : public mongo::unittest::Test { - public: - virtual void setUp() { - ReplicaSetConfig config; - ASSERT_OK(config.initialize( - BSON("_id" << "rs0" << - "version" << 2 << - "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) << - BSON("_id" << 4 << "host" << "host4" << "votes" << 0))))); - ASSERT_OK(config.validate()); - long long candidateId = 0; - long long term = 2; - OpTime lastOplogEntry = OpTime(Timestamp(999,0), 1); - - _requester.reset(new VoteRequester::Algorithm(config, - candidateId, - term, - false, // not a dryRun - lastOplogEntry)); - } - - virtual void tearDown() { - _requester.reset(NULL); - } - - protected: - int64_t countLogLinesContaining(const std::string& needle) { - return std::count_if(getCapturedLogMessages().begin(), - getCapturedLogMessages().end(), - stdx::bind(stringContains, - stdx::placeholders::_1, - needle)); - } - - bool hasReceivedSufficientResponses() { - return _requester->hasReceivedSufficientResponses(); - } - - void processResponse(const RemoteCommandRequest& request, const ResponseStatus& response) { - _requester->processResponse(request, response); - } - - VoteRequester::VoteRequestResult getResult() { - return _requester->getResult(); - } - - RemoteCommandRequest requestFrom(std::string hostname) { - return RemoteCommandRequest(HostAndPort(hostname), - "", // fields do not matter in VoteRequester - BSONObj(), - Milliseconds(0)); - } - - ResponseStatus badResponseStatus() { - return ResponseStatus(ErrorCodes::NodeNotFound, "not on my watch"); - } - - ResponseStatus votedYes() { - ReplSetRequestVotesResponse response; - response.setOk(true); - response.setVoteGranted(true); - response.setTerm(1); - return ResponseStatus(NetworkInterfaceMock::Response(response.toBSON(), - Milliseconds(10))); - } - - ResponseStatus votedNoBecauseConfigVersionDoesNotMatch() { - ReplSetRequestVotesResponse response; - response.setOk(true); - response.setVoteGranted(false); - response.setTerm(1); - response.setReason("candidate's config version differs from mine"); - return ResponseStatus(NetworkInterfaceMock::Response(response.toBSON(), - Milliseconds(10))); - } - - ResponseStatus votedNoBecauseSetNameDiffers() { - ReplSetRequestVotesResponse response; - response.setOk(true); - response.setVoteGranted(false); - response.setTerm(1); - response.setReason("candidate's set name differs from mine"); - return ResponseStatus(NetworkInterfaceMock::Response(response.toBSON(), - Milliseconds(10))); - } - - ResponseStatus votedNoBecauseLastOpTimeIsGreater() { - ReplSetRequestVotesResponse response; - response.setOk(true); - response.setVoteGranted(false); - response.setTerm(1); - response.setReason("candidate's data is staler than mine"); - return ResponseStatus(NetworkInterfaceMock::Response(response.toBSON(), - Milliseconds(10))); - } - - ResponseStatus votedNoBecauseTermIsGreater() { - ReplSetRequestVotesResponse response; - response.setOk(true); - response.setVoteGranted(false); - response.setTerm(3); - response.setReason("candidate's term is lower than mine"); - return ResponseStatus(NetworkInterfaceMock::Response(response.toBSON(), - Milliseconds(10))); - } - - ResponseStatus votedNoBecauseAlreadyVoted() { - ReplSetRequestVotesResponse response; - response.setOk(true); - response.setVoteGranted(false); - response.setTerm(2); - response.setReason("already voted for another candidate this term"); - return ResponseStatus(NetworkInterfaceMock::Response(response.toBSON(), - Milliseconds(10))); - } - - std::unique_ptr<VoteRequester::Algorithm> _requester; - }; - - class VoteRequesterDryRunTest : public VoteRequesterTest { - public: - virtual void setUp() { - ReplicaSetConfig config; - ASSERT_OK(config.initialize( - BSON("_id" << "rs0" << - "version" << 2 << - "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) << - BSON("_id" << 4 << "host" << "host4" << "votes" << 0))))); - ASSERT_OK(config.validate()); - long long candidateId = 0; - long long term = 2; - OpTime lastOplogEntry = OpTime(Timestamp(999,0), 1); - - _requester.reset(new VoteRequester::Algorithm(config, - candidateId, - term, - true, // dryRun - lastOplogEntry)); - } - - }; - - TEST_F(VoteRequesterTest, ImmediateGoodResponseWinElection) { - ASSERT_FALSE(hasReceivedSufficientResponses()); - processResponse(requestFrom("host1"), votedYes()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); - } - - TEST_F(VoteRequesterTest, BadConfigVersionWinElection) { - startCapturingLogMessages(); - ASSERT_FALSE(hasReceivedSufficientResponses()); - processResponse(requestFrom("host1"), votedNoBecauseConfigVersionDoesNotMatch()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); - processResponse(requestFrom("host2"), votedYes()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); - stopCapturingLogMessages(); +using executor::NetworkInterfaceMock; +using unittest::assertGet; + +using RemoteCommandRequest = RemoteCommandRequest; + +bool stringContains(const std::string& haystack, const std::string& needle) { + return haystack.find(needle) != std::string::npos; +} + + +class VoteRequesterTest : public mongo::unittest::Test { +public: + virtual void setUp() { + ReplicaSetConfig config; + ASSERT_OK(config.initialize(BSON("_id" + << "rs0" + << "version" << 2 << "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) + << BSON("_id" << 4 << "host" + << "host4" + << "votes" << 0))))); + ASSERT_OK(config.validate()); + long long candidateId = 0; + long long term = 2; + OpTime lastOplogEntry = OpTime(Timestamp(999, 0), 1); + + _requester.reset(new VoteRequester::Algorithm(config, + candidateId, + term, + false, // not a dryRun + lastOplogEntry)); } - TEST_F(VoteRequesterTest, SetNameDiffersWinElection) { - startCapturingLogMessages(); - ASSERT_FALSE(hasReceivedSufficientResponses()); - processResponse(requestFrom("host1"), votedNoBecauseSetNameDiffers()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); - processResponse(requestFrom("host2"), votedYes()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); - stopCapturingLogMessages(); + virtual void tearDown() { + _requester.reset(NULL); } - TEST_F(VoteRequesterTest, LastOpTimeIsGreaterWinElection) { - startCapturingLogMessages(); - ASSERT_FALSE(hasReceivedSufficientResponses()); - processResponse(requestFrom("host1"), votedNoBecauseLastOpTimeIsGreater()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); - processResponse(requestFrom("host2"), votedYes()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); - stopCapturingLogMessages(); +protected: + int64_t countLogLinesContaining(const std::string& needle) { + return std::count_if(getCapturedLogMessages().begin(), + getCapturedLogMessages().end(), + stdx::bind(stringContains, stdx::placeholders::_1, needle)); } - TEST_F(VoteRequesterTest, FailedToContactWinElection) { - startCapturingLogMessages(); - ASSERT_FALSE(hasReceivedSufficientResponses()); - processResponse(requestFrom("host1"), badResponseStatus()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(1, countLogLinesContaining("Got failed response from host1")); - processResponse(requestFrom("host2"), votedYes()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); - stopCapturingLogMessages(); + bool hasReceivedSufficientResponses() { + return _requester->hasReceivedSufficientResponses(); } - TEST_F(VoteRequesterTest, AlreadyVotedWinElection) { - startCapturingLogMessages(); - ASSERT_FALSE(hasReceivedSufficientResponses()); - processResponse(requestFrom("host1"), votedNoBecauseAlreadyVoted()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); - processResponse(requestFrom("host2"), votedYes()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); - stopCapturingLogMessages(); + void processResponse(const RemoteCommandRequest& request, const ResponseStatus& response) { + _requester->processResponse(request, response); } - TEST_F(VoteRequesterTest, StaleTermLoseElection) { - startCapturingLogMessages(); - ASSERT_FALSE(hasReceivedSufficientResponses()); - processResponse(requestFrom("host1"), votedNoBecauseTermIsGreater()); - ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(VoteRequester::StaleTerm, getResult()); - stopCapturingLogMessages(); + VoteRequester::VoteRequestResult getResult() { + return _requester->getResult(); } - TEST_F(VoteRequesterTest, NotEnoughVotesLoseElection) { - startCapturingLogMessages(); - ASSERT_FALSE(hasReceivedSufficientResponses()); - processResponse(requestFrom("host1"), votedNoBecauseSetNameDiffers()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); - processResponse(requestFrom("host2"), badResponseStatus()); - ASSERT_EQUALS(1, countLogLinesContaining("Got failed response from host2")); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(VoteRequester::InsufficientVotes, getResult()); - stopCapturingLogMessages(); + RemoteCommandRequest requestFrom(std::string hostname) { + return RemoteCommandRequest(HostAndPort(hostname), + "", // fields do not matter in VoteRequester + BSONObj(), + Milliseconds(0)); } - TEST_F(VoteRequesterDryRunTest, ImmediateGoodResponseWinElection) { - ASSERT_FALSE(hasReceivedSufficientResponses()); - processResponse(requestFrom("host1"), votedYes()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); + ResponseStatus badResponseStatus() { + return ResponseStatus(ErrorCodes::NodeNotFound, "not on my watch"); } - TEST_F(VoteRequesterDryRunTest, BadConfigVersionWinElection) { - startCapturingLogMessages(); - ASSERT_FALSE(hasReceivedSufficientResponses()); - processResponse(requestFrom("host1"), votedNoBecauseConfigVersionDoesNotMatch()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); - processResponse(requestFrom("host2"), votedYes()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); - stopCapturingLogMessages(); + ResponseStatus votedYes() { + ReplSetRequestVotesResponse response; + response.setOk(true); + response.setVoteGranted(true); + response.setTerm(1); + return ResponseStatus(NetworkInterfaceMock::Response(response.toBSON(), Milliseconds(10))); } - TEST_F(VoteRequesterDryRunTest, SetNameDiffersWinElection) { - startCapturingLogMessages(); - ASSERT_FALSE(hasReceivedSufficientResponses()); - processResponse(requestFrom("host1"), votedNoBecauseSetNameDiffers()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); - processResponse(requestFrom("host2"), votedYes()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); - stopCapturingLogMessages(); + ResponseStatus votedNoBecauseConfigVersionDoesNotMatch() { + ReplSetRequestVotesResponse response; + response.setOk(true); + response.setVoteGranted(false); + response.setTerm(1); + response.setReason("candidate's config version differs from mine"); + return ResponseStatus(NetworkInterfaceMock::Response(response.toBSON(), Milliseconds(10))); } - TEST_F(VoteRequesterDryRunTest, LastOpTimeIsGreaterWinElection) { - startCapturingLogMessages(); - ASSERT_FALSE(hasReceivedSufficientResponses()); - processResponse(requestFrom("host1"), votedNoBecauseLastOpTimeIsGreater()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); - processResponse(requestFrom("host2"), votedYes()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); - stopCapturingLogMessages(); + ResponseStatus votedNoBecauseSetNameDiffers() { + ReplSetRequestVotesResponse response; + response.setOk(true); + response.setVoteGranted(false); + response.setTerm(1); + response.setReason("candidate's set name differs from mine"); + return ResponseStatus(NetworkInterfaceMock::Response(response.toBSON(), Milliseconds(10))); } - TEST_F(VoteRequesterDryRunTest, FailedToContactWinElection) { - startCapturingLogMessages(); - ASSERT_FALSE(hasReceivedSufficientResponses()); - processResponse(requestFrom("host1"), badResponseStatus()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(1, countLogLinesContaining("Got failed response from host1")); - processResponse(requestFrom("host2"), votedYes()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); - stopCapturingLogMessages(); + ResponseStatus votedNoBecauseLastOpTimeIsGreater() { + ReplSetRequestVotesResponse response; + response.setOk(true); + response.setVoteGranted(false); + response.setTerm(1); + response.setReason("candidate's data is staler than mine"); + return ResponseStatus(NetworkInterfaceMock::Response(response.toBSON(), Milliseconds(10))); } - TEST_F(VoteRequesterDryRunTest, AlreadyVotedWinElection) { - startCapturingLogMessages(); - ASSERT_FALSE(hasReceivedSufficientResponses()); - processResponse(requestFrom("host1"), votedNoBecauseAlreadyVoted()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); - processResponse(requestFrom("host2"), votedYes()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); - stopCapturingLogMessages(); + ResponseStatus votedNoBecauseTermIsGreater() { + ReplSetRequestVotesResponse response; + response.setOk(true); + response.setVoteGranted(false); + response.setTerm(3); + response.setReason("candidate's term is lower than mine"); + return ResponseStatus(NetworkInterfaceMock::Response(response.toBSON(), Milliseconds(10))); } - TEST_F(VoteRequesterDryRunTest, StaleTermLoseElection) { - startCapturingLogMessages(); - ASSERT_FALSE(hasReceivedSufficientResponses()); - processResponse(requestFrom("host1"), votedNoBecauseTermIsGreater()); - ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(VoteRequester::StaleTerm, getResult()); - stopCapturingLogMessages(); + ResponseStatus votedNoBecauseAlreadyVoted() { + ReplSetRequestVotesResponse response; + response.setOk(true); + response.setVoteGranted(false); + response.setTerm(2); + response.setReason("already voted for another candidate this term"); + return ResponseStatus(NetworkInterfaceMock::Response(response.toBSON(), Milliseconds(10))); } - TEST_F(VoteRequesterDryRunTest, NotEnoughVotesLoseElection) { - startCapturingLogMessages(); - ASSERT_FALSE(hasReceivedSufficientResponses()); - processResponse(requestFrom("host1"), votedNoBecauseSetNameDiffers()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); - processResponse(requestFrom("host2"), badResponseStatus()); - ASSERT_EQUALS(1, countLogLinesContaining("Got failed response from host2")); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(VoteRequester::InsufficientVotes, getResult()); - stopCapturingLogMessages(); + std::unique_ptr<VoteRequester::Algorithm> _requester; +}; + +class VoteRequesterDryRunTest : public VoteRequesterTest { +public: + virtual void setUp() { + ReplicaSetConfig config; + ASSERT_OK(config.initialize(BSON("_id" + << "rs0" + << "version" << 2 << "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) + << BSON("_id" << 4 << "host" + << "host4" + << "votes" << 0))))); + ASSERT_OK(config.validate()); + long long candidateId = 0; + long long term = 2; + OpTime lastOplogEntry = OpTime(Timestamp(999, 0), 1); + + _requester.reset(new VoteRequester::Algorithm(config, + candidateId, + term, + true, // dryRun + lastOplogEntry)); } +}; + +TEST_F(VoteRequesterTest, ImmediateGoodResponseWinElection) { + ASSERT_FALSE(hasReceivedSufficientResponses()); + processResponse(requestFrom("host1"), votedYes()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); +} + +TEST_F(VoteRequesterTest, BadConfigVersionWinElection) { + startCapturingLogMessages(); + ASSERT_FALSE(hasReceivedSufficientResponses()); + processResponse(requestFrom("host1"), votedNoBecauseConfigVersionDoesNotMatch()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); + processResponse(requestFrom("host2"), votedYes()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); + stopCapturingLogMessages(); +} + +TEST_F(VoteRequesterTest, SetNameDiffersWinElection) { + startCapturingLogMessages(); + ASSERT_FALSE(hasReceivedSufficientResponses()); + processResponse(requestFrom("host1"), votedNoBecauseSetNameDiffers()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); + processResponse(requestFrom("host2"), votedYes()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); + stopCapturingLogMessages(); +} + +TEST_F(VoteRequesterTest, LastOpTimeIsGreaterWinElection) { + startCapturingLogMessages(); + ASSERT_FALSE(hasReceivedSufficientResponses()); + processResponse(requestFrom("host1"), votedNoBecauseLastOpTimeIsGreater()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); + processResponse(requestFrom("host2"), votedYes()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); + stopCapturingLogMessages(); +} + +TEST_F(VoteRequesterTest, FailedToContactWinElection) { + startCapturingLogMessages(); + ASSERT_FALSE(hasReceivedSufficientResponses()); + processResponse(requestFrom("host1"), badResponseStatus()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(1, countLogLinesContaining("Got failed response from host1")); + processResponse(requestFrom("host2"), votedYes()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); + stopCapturingLogMessages(); +} + +TEST_F(VoteRequesterTest, AlreadyVotedWinElection) { + startCapturingLogMessages(); + ASSERT_FALSE(hasReceivedSufficientResponses()); + processResponse(requestFrom("host1"), votedNoBecauseAlreadyVoted()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); + processResponse(requestFrom("host2"), votedYes()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); + stopCapturingLogMessages(); +} + +TEST_F(VoteRequesterTest, StaleTermLoseElection) { + startCapturingLogMessages(); + ASSERT_FALSE(hasReceivedSufficientResponses()); + processResponse(requestFrom("host1"), votedNoBecauseTermIsGreater()); + ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(VoteRequester::StaleTerm, getResult()); + stopCapturingLogMessages(); +} + +TEST_F(VoteRequesterTest, NotEnoughVotesLoseElection) { + startCapturingLogMessages(); + ASSERT_FALSE(hasReceivedSufficientResponses()); + processResponse(requestFrom("host1"), votedNoBecauseSetNameDiffers()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); + processResponse(requestFrom("host2"), badResponseStatus()); + ASSERT_EQUALS(1, countLogLinesContaining("Got failed response from host2")); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(VoteRequester::InsufficientVotes, getResult()); + stopCapturingLogMessages(); +} + +TEST_F(VoteRequesterDryRunTest, ImmediateGoodResponseWinElection) { + ASSERT_FALSE(hasReceivedSufficientResponses()); + processResponse(requestFrom("host1"), votedYes()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); +} + +TEST_F(VoteRequesterDryRunTest, BadConfigVersionWinElection) { + startCapturingLogMessages(); + ASSERT_FALSE(hasReceivedSufficientResponses()); + processResponse(requestFrom("host1"), votedNoBecauseConfigVersionDoesNotMatch()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); + processResponse(requestFrom("host2"), votedYes()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); + stopCapturingLogMessages(); +} + +TEST_F(VoteRequesterDryRunTest, SetNameDiffersWinElection) { + startCapturingLogMessages(); + ASSERT_FALSE(hasReceivedSufficientResponses()); + processResponse(requestFrom("host1"), votedNoBecauseSetNameDiffers()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); + processResponse(requestFrom("host2"), votedYes()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); + stopCapturingLogMessages(); +} + +TEST_F(VoteRequesterDryRunTest, LastOpTimeIsGreaterWinElection) { + startCapturingLogMessages(); + ASSERT_FALSE(hasReceivedSufficientResponses()); + processResponse(requestFrom("host1"), votedNoBecauseLastOpTimeIsGreater()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); + processResponse(requestFrom("host2"), votedYes()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); + stopCapturingLogMessages(); +} + +TEST_F(VoteRequesterDryRunTest, FailedToContactWinElection) { + startCapturingLogMessages(); + ASSERT_FALSE(hasReceivedSufficientResponses()); + processResponse(requestFrom("host1"), badResponseStatus()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(1, countLogLinesContaining("Got failed response from host1")); + processResponse(requestFrom("host2"), votedYes()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); + stopCapturingLogMessages(); +} + +TEST_F(VoteRequesterDryRunTest, AlreadyVotedWinElection) { + startCapturingLogMessages(); + ASSERT_FALSE(hasReceivedSufficientResponses()); + processResponse(requestFrom("host1"), votedNoBecauseAlreadyVoted()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); + processResponse(requestFrom("host2"), votedYes()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(VoteRequester::SuccessfullyElected, getResult()); + stopCapturingLogMessages(); +} + +TEST_F(VoteRequesterDryRunTest, StaleTermLoseElection) { + startCapturingLogMessages(); + ASSERT_FALSE(hasReceivedSufficientResponses()); + processResponse(requestFrom("host1"), votedNoBecauseTermIsGreater()); + ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(VoteRequester::StaleTerm, getResult()); + stopCapturingLogMessages(); +} + +TEST_F(VoteRequesterDryRunTest, NotEnoughVotesLoseElection) { + startCapturingLogMessages(); + ASSERT_FALSE(hasReceivedSufficientResponses()); + processResponse(requestFrom("host1"), votedNoBecauseSetNameDiffers()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(1, countLogLinesContaining("Got no vote from host1")); + processResponse(requestFrom("host2"), badResponseStatus()); + ASSERT_EQUALS(1, countLogLinesContaining("Got failed response from host2")); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(VoteRequester::InsufficientVotes, getResult()); + stopCapturingLogMessages(); +} } // namespace } // namespace repl |