diff options
Diffstat (limited to 'src/mongo/db/repl/elect_cmd_runner_test.cpp')
-rw-r--r-- | src/mongo/db/repl/elect_cmd_runner_test.cpp | 672 |
1 files changed, 331 insertions, 341 deletions
diff --git a/src/mongo/db/repl/elect_cmd_runner_test.cpp b/src/mongo/db/repl/elect_cmd_runner_test.cpp index c029994f30d..91f2bbaea5a 100644 --- a/src/mongo/db/repl/elect_cmd_runner_test.cpp +++ b/src/mongo/db/repl/elect_cmd_runner_test.cpp @@ -47,379 +47,369 @@ namespace mongo { namespace repl { namespace { - using executor::NetworkInterfaceMock; - - class ElectCmdRunnerTest : public mongo::unittest::Test { - public: - void startTest(ElectCmdRunner* electCmdRunner, - const ReplicaSetConfig& currentConfig, - int selfIndex, - const std::vector<HostAndPort>& hosts); - - void waitForTest(); - - void electCmdRunnerRunner(const ReplicationExecutor::CallbackArgs& data, - ElectCmdRunner* electCmdRunner, - StatusWith<ReplicationExecutor::EventHandle>* evh, - const ReplicaSetConfig& currentConfig, - int selfIndex, - const std::vector<HostAndPort>& hosts); - - NetworkInterfaceMock* _net; - StorageInterfaceMock* _storage; - std::unique_ptr<ReplicationExecutor> _executor; - std::unique_ptr<stdx::thread> _executorThread; - - private: - void setUp(); - void tearDown(); - - ReplicationExecutor::EventHandle _allDoneEvent; - }; - - void ElectCmdRunnerTest::setUp() { - _net = new NetworkInterfaceMock; - _storage = new StorageInterfaceMock; - _executor.reset(new ReplicationExecutor(_net, _storage, 1 /* prng seed */)); - _executorThread.reset(new stdx::thread(stdx::bind(&ReplicationExecutor::run, - _executor.get()))); - } - - void ElectCmdRunnerTest::tearDown() { - _executor->shutdown(); - _executorThread->join(); +using executor::NetworkInterfaceMock; + +class ElectCmdRunnerTest : public mongo::unittest::Test { +public: + void startTest(ElectCmdRunner* electCmdRunner, + const ReplicaSetConfig& currentConfig, + int selfIndex, + const std::vector<HostAndPort>& hosts); + + void waitForTest(); + + void electCmdRunnerRunner(const ReplicationExecutor::CallbackArgs& data, + ElectCmdRunner* electCmdRunner, + StatusWith<ReplicationExecutor::EventHandle>* evh, + const ReplicaSetConfig& currentConfig, + int selfIndex, + const std::vector<HostAndPort>& hosts); + + NetworkInterfaceMock* _net; + StorageInterfaceMock* _storage; + std::unique_ptr<ReplicationExecutor> _executor; + std::unique_ptr<stdx::thread> _executorThread; + +private: + void setUp(); + void tearDown(); + + ReplicationExecutor::EventHandle _allDoneEvent; +}; + +void ElectCmdRunnerTest::setUp() { + _net = new NetworkInterfaceMock; + _storage = new StorageInterfaceMock; + _executor.reset(new ReplicationExecutor(_net, _storage, 1 /* prng seed */)); + _executorThread.reset(new stdx::thread(stdx::bind(&ReplicationExecutor::run, _executor.get()))); +} + +void ElectCmdRunnerTest::tearDown() { + _executor->shutdown(); + _executorThread->join(); +} + +ReplicaSetConfig assertMakeRSConfig(const BSONObj& configBson) { + ReplicaSetConfig config; + ASSERT_OK(config.initialize(configBson)); + ASSERT_OK(config.validate()); + return config; +} + +const BSONObj makeElectRequest(const ReplicaSetConfig& rsConfig, int selfIndex) { + const MemberConfig& myConfig = rsConfig.getMemberAt(selfIndex); + return BSON("replSetElect" << 1 << "set" << rsConfig.getReplSetName() << "who" + << myConfig.getHostAndPort().toString() << "whoid" + << myConfig.getId() << "cfgver" << rsConfig.getConfigVersion() + << "round" << 380865962699346850ll); +} + +BSONObj stripRound(const BSONObj& orig) { + BSONObjBuilder builder; + for (BSONObjIterator iter(orig); iter.more(); iter.next()) { + BSONElement e = *iter; + if (e.fieldNameStringData() == "round") { + continue; + } + builder.append(e); } + return builder.obj(); +} + +// This is necessary because the run method must be scheduled in the Replication Executor +// for correct concurrency operation. +void ElectCmdRunnerTest::electCmdRunnerRunner(const ReplicationExecutor::CallbackArgs& data, + ElectCmdRunner* electCmdRunner, + StatusWith<ReplicationExecutor::EventHandle>* evh, + const ReplicaSetConfig& currentConfig, + int selfIndex, + const std::vector<HostAndPort>& hosts) { + invariant(data.status.isOK()); + ReplicationExecutor* executor = dynamic_cast<ReplicationExecutor*>(data.executor); + ASSERT(executor); + *evh = electCmdRunner->start(executor, currentConfig, selfIndex, hosts); +} + +void ElectCmdRunnerTest::startTest(ElectCmdRunner* electCmdRunner, + const ReplicaSetConfig& currentConfig, + int selfIndex, + const std::vector<HostAndPort>& hosts) { + StatusWith<ReplicationExecutor::EventHandle> evh(ErrorCodes::InternalError, "Not set"); + StatusWith<ReplicationExecutor::CallbackHandle> cbh = + _executor->scheduleWork(stdx::bind(&ElectCmdRunnerTest::electCmdRunnerRunner, + this, + stdx::placeholders::_1, + electCmdRunner, + &evh, + currentConfig, + selfIndex, + hosts)); + ASSERT_OK(cbh.getStatus()); + _executor->wait(cbh.getValue()); + ASSERT_OK(evh.getStatus()); + _allDoneEvent = evh.getValue(); +} + +void ElectCmdRunnerTest::waitForTest() { + _executor->waitForEvent(_allDoneEvent); +} + +TEST_F(ElectCmdRunnerTest, OneNode) { + // Only one node in the config. + const ReplicaSetConfig config = assertMakeRSConfig(BSON("_id" + << "rs0" + << "version" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h1")))); + + std::vector<HostAndPort> hosts; + ElectCmdRunner electCmdRunner; + startTest(&electCmdRunner, config, 0, hosts); + waitForTest(); + ASSERT_EQUALS(electCmdRunner.getReceivedVotes(), 1); +} + +TEST_F(ElectCmdRunnerTest, TwoNodes) { + // Two nodes, we are node h1. + const ReplicaSetConfig config = + assertMakeRSConfig(BSON("_id" + << "rs0" + << "version" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h0") + << BSON("_id" << 2 << "host" + << "h1")))); + + std::vector<HostAndPort> hosts; + hosts.push_back(config.getMemberAt(1).getHostAndPort()); + + const BSONObj electRequest = makeElectRequest(config, 0); + + ElectCmdRunner electCmdRunner; + startTest(&electCmdRunner, config, 0, hosts); + const Date_t startDate = _net->now(); + _net->enterNetwork(); + const NetworkInterfaceMock::NetworkOperationIterator noi = _net->getNextReadyRequest(); + ASSERT_EQUALS("admin", noi->getRequest().dbname); + ASSERT_EQUALS(stripRound(electRequest), stripRound(noi->getRequest().cmdObj)); + ASSERT_EQUALS(HostAndPort("h1"), noi->getRequest().target); + _net->scheduleResponse( + noi, + startDate + Milliseconds(10), + ResponseStatus(RemoteCommandResponse( + BSON("ok" << 1 << "vote" << 1 << "round" << 380865962699346850ll), Milliseconds(8)))); + _net->runUntil(startDate + Milliseconds(10)); + _net->exitNetwork(); + ASSERT_EQUALS(startDate + Milliseconds(10), _net->now()); + waitForTest(); + ASSERT_EQUALS(electCmdRunner.getReceivedVotes(), 2); +} + +TEST_F(ElectCmdRunnerTest, ShuttingDown) { + // Two nodes, we are node h1. Shutdown happens while we're scheduling remote commands. + ReplicaSetConfig config = assertMakeRSConfig(BSON("_id" + << "rs0" + << "version" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 1 << "host" + << "h0") + << BSON("_id" << 2 << "host" + << "h1")))); + + std::vector<HostAndPort> hosts; + hosts.push_back(config.getMemberAt(1).getHostAndPort()); + + ElectCmdRunner electCmdRunner; + StatusWith<ReplicationExecutor::EventHandle> evh(ErrorCodes::InternalError, "Not set"); + StatusWith<ReplicationExecutor::CallbackHandle> cbh = + _executor->scheduleWork(stdx::bind(&ElectCmdRunnerTest::electCmdRunnerRunner, + this, + stdx::placeholders::_1, + &electCmdRunner, + &evh, + config, + 0, + hosts)); + ASSERT_OK(cbh.getStatus()); + _executor->wait(cbh.getValue()); + ASSERT_OK(evh.getStatus()); + _executor->shutdown(); + _executor->waitForEvent(evh.getValue()); + ASSERT_EQUALS(electCmdRunner.getReceivedVotes(), 1); +} + +class ElectScatterGatherTest : public mongo::unittest::Test { +public: + virtual void start(const BSONObj& configObj) { + int selfConfigIndex = 0; - ReplicaSetConfig assertMakeRSConfig(const BSONObj& configBson) { ReplicaSetConfig config; - ASSERT_OK(config.initialize(configBson)); - ASSERT_OK(config.validate()); - return config; - } + config.initialize(configObj); - const BSONObj makeElectRequest(const ReplicaSetConfig& rsConfig, - int selfIndex) { - const MemberConfig& myConfig = rsConfig.getMemberAt(selfIndex); - return BSON("replSetElect" << 1 << - "set" << rsConfig.getReplSetName() << - "who" << myConfig.getHostAndPort().toString() << - "whoid" << myConfig.getId() << - "cfgver" << rsConfig.getConfigVersion() << - "round" << 380865962699346850ll); - } - - BSONObj stripRound(const BSONObj& orig) { - BSONObjBuilder builder; - for (BSONObjIterator iter(orig); iter.more(); iter.next()) { - BSONElement e = *iter; - if (e.fieldNameStringData() == "round") { - continue; - } - builder.append(e); + std::vector<HostAndPort> hosts; + for (ReplicaSetConfig::MemberIterator mem = ++config.membersBegin(); + mem != config.membersEnd(); + ++mem) { + hosts.push_back(mem->getHostAndPort()); } - return builder.obj(); - } - // This is necessary because the run method must be scheduled in the Replication Executor - // for correct concurrency operation. - void ElectCmdRunnerTest::electCmdRunnerRunner( - const ReplicationExecutor::CallbackArgs& data, - ElectCmdRunner* electCmdRunner, - StatusWith<ReplicationExecutor::EventHandle>* evh, - const ReplicaSetConfig& currentConfig, - int selfIndex, - const std::vector<HostAndPort>& hosts) { - - invariant(data.status.isOK()); - ReplicationExecutor* executor = dynamic_cast<ReplicationExecutor*>(data.executor); - ASSERT(executor); - *evh = electCmdRunner->start( - executor, - currentConfig, - selfIndex, - hosts); + _checker.reset(new ElectCmdRunner::Algorithm(config, selfConfigIndex, hosts, OID())); } - void ElectCmdRunnerTest::startTest(ElectCmdRunner* electCmdRunner, - const ReplicaSetConfig& currentConfig, - int selfIndex, - const std::vector<HostAndPort>& hosts) { - - StatusWith<ReplicationExecutor::EventHandle> evh(ErrorCodes::InternalError, "Not set"); - StatusWith<ReplicationExecutor::CallbackHandle> cbh = - _executor->scheduleWork( - stdx::bind(&ElectCmdRunnerTest::electCmdRunnerRunner, - this, - stdx::placeholders::_1, - electCmdRunner, - &evh, - currentConfig, - selfIndex, - hosts)); - ASSERT_OK(cbh.getStatus()); - _executor->wait(cbh.getValue()); - ASSERT_OK(evh.getStatus()); - _allDoneEvent = evh.getValue(); + virtual void tearDown() { + _checker.reset(NULL); } - void ElectCmdRunnerTest::waitForTest() { - _executor->waitForEvent(_allDoneEvent); +protected: + bool hasReceivedSufficientResponses() { + return _checker->hasReceivedSufficientResponses(); } - TEST_F(ElectCmdRunnerTest, OneNode) { - // Only one node in the config. - const ReplicaSetConfig config = assertMakeRSConfig( - BSON("_id" << "rs0" << - "version" << 1 << - "members" << BSON_ARRAY( - BSON("_id" << 1 << "host" << "h1")))); - - std::vector<HostAndPort> hosts; - ElectCmdRunner electCmdRunner; - startTest(&electCmdRunner, config, 0, hosts); - waitForTest(); - ASSERT_EQUALS(electCmdRunner.getReceivedVotes(), 1); + int getReceivedVotes() { + return _checker->getReceivedVotes(); } - TEST_F(ElectCmdRunnerTest, TwoNodes) { - // Two nodes, we are node h1. - const ReplicaSetConfig config = assertMakeRSConfig( - BSON("_id" << "rs0" << - "version" << 1 << - "members" << BSON_ARRAY( - BSON("_id" << 1 << "host" << "h0") << - BSON("_id" << 2 << "host" << "h1")))); - - std::vector<HostAndPort> hosts; - hosts.push_back(config.getMemberAt(1).getHostAndPort()); - - const BSONObj electRequest = makeElectRequest(config, 0); - - ElectCmdRunner electCmdRunner; - startTest(&electCmdRunner, config, 0, hosts); - const Date_t startDate = _net->now(); - _net->enterNetwork(); - const NetworkInterfaceMock::NetworkOperationIterator noi = _net->getNextReadyRequest(); - ASSERT_EQUALS("admin", noi->getRequest().dbname); - ASSERT_EQUALS(stripRound(electRequest), stripRound(noi->getRequest().cmdObj)); - ASSERT_EQUALS(HostAndPort("h1"), noi->getRequest().target); - _net->scheduleResponse(noi, - startDate + Milliseconds(10), - ResponseStatus(RemoteCommandResponse( - BSON("ok" << 1 << - "vote" << 1 << - "round" << 380865962699346850ll), - Milliseconds(8)))); - _net->runUntil(startDate + Milliseconds(10)); - _net->exitNetwork(); - ASSERT_EQUALS(startDate + Milliseconds(10), _net->now()); - waitForTest(); - ASSERT_EQUALS(electCmdRunner.getReceivedVotes(), 2); + void processResponse(const RemoteCommandRequest& request, const ResponseStatus& response) { + _checker->processResponse(request, response); } - TEST_F(ElectCmdRunnerTest, ShuttingDown) { - // Two nodes, we are node h1. Shutdown happens while we're scheduling remote commands. - ReplicaSetConfig config = assertMakeRSConfig( - BSON("_id" << "rs0" << - "version" << 1 << - "members" << BSON_ARRAY( - BSON("_id" << 1 << "host" << "h0") << - BSON("_id" << 2 << "host" << "h1")))); - - std::vector<HostAndPort> hosts; - hosts.push_back(config.getMemberAt(1).getHostAndPort()); - - ElectCmdRunner electCmdRunner; - StatusWith<ReplicationExecutor::EventHandle> evh(ErrorCodes::InternalError, "Not set"); - StatusWith<ReplicationExecutor::CallbackHandle> cbh = - _executor->scheduleWork( - stdx::bind(&ElectCmdRunnerTest::electCmdRunnerRunner, - this, - stdx::placeholders::_1, - &electCmdRunner, - &evh, - config, - 0, - hosts)); - ASSERT_OK(cbh.getStatus()); - _executor->wait(cbh.getValue()); - ASSERT_OK(evh.getStatus()); - _executor->shutdown(); - _executor->waitForEvent(evh.getValue()); - ASSERT_EQUALS(electCmdRunner.getReceivedVotes(), 1); + RemoteCommandRequest requestFrom(std::string hostname) { + return RemoteCommandRequest(HostAndPort(hostname), + "", // the non-hostname fields do not matter for Elect + BSONObj(), + Milliseconds(0)); } - class ElectScatterGatherTest : public mongo::unittest::Test { - public: - virtual void start(const BSONObj& configObj) { - int selfConfigIndex = 0; - - ReplicaSetConfig config; - config.initialize(configObj); - - std::vector<HostAndPort> hosts; - for (ReplicaSetConfig::MemberIterator mem = ++config.membersBegin(); - mem != config.membersEnd(); - ++mem) { - hosts.push_back(mem->getHostAndPort()); - } - - _checker.reset(new ElectCmdRunner::Algorithm(config, - selfConfigIndex, - hosts, - OID())); - } - - virtual void tearDown() { - _checker.reset(NULL); - } - - protected: - bool hasReceivedSufficientResponses() { - return _checker->hasReceivedSufficientResponses(); - } - - int getReceivedVotes() { - return _checker->getReceivedVotes(); - } - - void processResponse(const RemoteCommandRequest& request, const ResponseStatus& response) { - _checker->processResponse(request, response); - } - - RemoteCommandRequest requestFrom(std::string hostname) { - return RemoteCommandRequest(HostAndPort(hostname), - "", // the non-hostname fields do not matter for Elect - BSONObj(), - Milliseconds(0)); - } - - ResponseStatus badResponseStatus() { - return ResponseStatus(ErrorCodes::NodeNotFound, "not on my watch"); - } - - ResponseStatus wrongTypeForVoteField() { - return ResponseStatus(NetworkInterfaceMock::Response(BSON("vote" << std::string("yea")), - Milliseconds(10))); - } - - ResponseStatus voteYea() { - return ResponseStatus(NetworkInterfaceMock::Response(BSON("vote" << 1), - Milliseconds(10))); - } - - ResponseStatus voteNay() { - return ResponseStatus(NetworkInterfaceMock::Response(BSON("vote" << -10000), - Milliseconds(10))); - } - - ResponseStatus abstainFromVoting() { - return ResponseStatus(NetworkInterfaceMock::Response(BSON("vote" << 0), - Milliseconds(10))); - } - - BSONObj threeNodesTwoArbitersConfig() { - return BSON("_id" << "rs0" << - "version" << 1 << - "members" << BSON_ARRAY( - BSON("_id" << 0 << "host" << "host0") << - BSON("_id" << 1 << "host" << "host1" << "arbiterOnly" << true) << - BSON("_id" << 2 << "host" << "host2" << "arbiterOnly" << true))); - } - - BSONObj basicThreeNodeConfig() { - return BSON("_id" << "rs0" << - "version" << 1 << - "members" << BSON_ARRAY( - BSON("_id" << 0 << "host" << "host0") << - BSON("_id" << 1 << "host" << "host1") << - BSON("_id" << 2 << "host" << "host2"))); - } - - private: - unique_ptr<ElectCmdRunner::Algorithm> _checker; - }; - - TEST_F(ElectScatterGatherTest, NodeRespondsWithBadVoteType) { - start(basicThreeNodeConfig()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - - processResponse(requestFrom("host2"), wrongTypeForVoteField()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(1, getReceivedVotes()); // 1 because we have 1 vote and voted for ourself + ResponseStatus badResponseStatus() { + return ResponseStatus(ErrorCodes::NodeNotFound, "not on my watch"); } - TEST_F(ElectScatterGatherTest, NodeRespondsWithBadStatus) { - start(basicThreeNodeConfig()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - - processResponse(requestFrom("host2"), badResponseStatus()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - - processResponse(requestFrom("host3"), abstainFromVoting()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(1, getReceivedVotes()); // 1 because we have 1 vote and voted for ourself + ResponseStatus wrongTypeForVoteField() { + return ResponseStatus( + NetworkInterfaceMock::Response(BSON("vote" << std::string("yea")), Milliseconds(10))); } - TEST_F(ElectScatterGatherTest, FirstNodeRespondsWithYea) { - start(basicThreeNodeConfig()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - - processResponse(requestFrom("host2"), voteYea()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(2, getReceivedVotes()); + ResponseStatus voteYea() { + return ResponseStatus(NetworkInterfaceMock::Response(BSON("vote" << 1), Milliseconds(10))); } - TEST_F(ElectScatterGatherTest, FirstNodeRespondsWithNaySecondWithYea) { - start(basicThreeNodeConfig()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - - processResponse(requestFrom("host2"), voteNay()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(-9999, getReceivedVotes()); + ResponseStatus voteNay() { + return ResponseStatus( + NetworkInterfaceMock::Response(BSON("vote" << -10000), Milliseconds(10))); } - TEST_F(ElectScatterGatherTest, BothNodesAbstainFromVoting) { - start(basicThreeNodeConfig()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - - processResponse(requestFrom("host2"), abstainFromVoting()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - - processResponse(requestFrom("host3"), abstainFromVoting()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(1, getReceivedVotes()); + ResponseStatus abstainFromVoting() { + return ResponseStatus(NetworkInterfaceMock::Response(BSON("vote" << 0), Milliseconds(10))); } - TEST_F(ElectScatterGatherTest, NodeRespondsWithBadStatusArbiters) { - start(threeNodesTwoArbitersConfig()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - - processResponse(requestFrom("host2"), badResponseStatus()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - - processResponse(requestFrom("host3"), abstainFromVoting()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(1, getReceivedVotes()); // 1 because we have 1 vote and voted for ourself + BSONObj threeNodesTwoArbitersConfig() { + return BSON("_id" + << "rs0" + << "version" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "host0") + << BSON("_id" << 1 << "host" + << "host1" + << "arbiterOnly" << true) + << BSON("_id" << 2 << "host" + << "host2" + << "arbiterOnly" << true))); } - TEST_F(ElectScatterGatherTest, FirstNodeRespondsWithYeaArbiters) { - start(threeNodesTwoArbitersConfig()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - - processResponse(requestFrom("host2"), voteYea()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(2, getReceivedVotes()); + BSONObj basicThreeNodeConfig() { + return BSON("_id" + << "rs0" + << "version" << 1 << "members" + << BSON_ARRAY(BSON("_id" << 0 << "host" + << "host0") + << BSON("_id" << 1 << "host" + << "host1") << BSON("_id" << 2 << "host" + << "host2"))); } - TEST_F(ElectScatterGatherTest, FirstNodeRespondsWithNaySecondWithYeaArbiters) { - start(threeNodesTwoArbitersConfig()); - ASSERT_FALSE(hasReceivedSufficientResponses()); - - processResponse(requestFrom("host2"), voteNay()); - ASSERT_TRUE(hasReceivedSufficientResponses()); - ASSERT_EQUALS(-9999, getReceivedVotes()); - } +private: + unique_ptr<ElectCmdRunner::Algorithm> _checker; +}; + +TEST_F(ElectScatterGatherTest, NodeRespondsWithBadVoteType) { + start(basicThreeNodeConfig()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + + processResponse(requestFrom("host2"), wrongTypeForVoteField()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(1, getReceivedVotes()); // 1 because we have 1 vote and voted for ourself +} + +TEST_F(ElectScatterGatherTest, NodeRespondsWithBadStatus) { + start(basicThreeNodeConfig()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + + processResponse(requestFrom("host2"), badResponseStatus()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + + processResponse(requestFrom("host3"), abstainFromVoting()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(1, getReceivedVotes()); // 1 because we have 1 vote and voted for ourself +} + +TEST_F(ElectScatterGatherTest, FirstNodeRespondsWithYea) { + start(basicThreeNodeConfig()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + + processResponse(requestFrom("host2"), voteYea()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(2, getReceivedVotes()); +} + +TEST_F(ElectScatterGatherTest, FirstNodeRespondsWithNaySecondWithYea) { + start(basicThreeNodeConfig()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + + processResponse(requestFrom("host2"), voteNay()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(-9999, getReceivedVotes()); +} + +TEST_F(ElectScatterGatherTest, BothNodesAbstainFromVoting) { + start(basicThreeNodeConfig()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + + processResponse(requestFrom("host2"), abstainFromVoting()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + + processResponse(requestFrom("host3"), abstainFromVoting()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(1, getReceivedVotes()); +} + +TEST_F(ElectScatterGatherTest, NodeRespondsWithBadStatusArbiters) { + start(threeNodesTwoArbitersConfig()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + + processResponse(requestFrom("host2"), badResponseStatus()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + + processResponse(requestFrom("host3"), abstainFromVoting()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(1, getReceivedVotes()); // 1 because we have 1 vote and voted for ourself +} + +TEST_F(ElectScatterGatherTest, FirstNodeRespondsWithYeaArbiters) { + start(threeNodesTwoArbitersConfig()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + + processResponse(requestFrom("host2"), voteYea()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(2, getReceivedVotes()); +} + +TEST_F(ElectScatterGatherTest, FirstNodeRespondsWithNaySecondWithYeaArbiters) { + start(threeNodesTwoArbitersConfig()); + ASSERT_FALSE(hasReceivedSufficientResponses()); + + processResponse(requestFrom("host2"), voteNay()); + ASSERT_TRUE(hasReceivedSufficientResponses()); + ASSERT_EQUALS(-9999, getReceivedVotes()); +} } // namespace } // namespace repl |