summaryrefslogtreecommitdiff
path: root/src/mongo/db/repl/elect_cmd_runner_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/repl/elect_cmd_runner_test.cpp')
-rw-r--r--src/mongo/db/repl/elect_cmd_runner_test.cpp672
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